Objective C自定义惰性加载图像UITableView Cell

第一次加载远程图像到iPhone应用程序,并希望有一些帮助优化过程。 我目前所做的是获取图像,如果它不存在,并caching它。 主要目标是:

  • 只在需要的时候加载图片。
  • 保存图像供将来使用以减less数据消耗,并且允许用户在没有连接到互联网时具有有些function的应用程序。

我只是觉得我做得不够好。

下面是tableView中的一段代码:cellForRowAtIndexPath:

MVImageCell * cell = (MVImageCell *)[tableView dequeueReusableCellWithIdentifier:@"PicsAndVideosCell"]; // empty cell cell.imageView.image = nil; cell.textLabel.text = nil; cell.detailTextLabel.text = nil; // set cell properties cell.textLabel.lineBreakMode = UILineBreakModeWordWrap; cell.textLabel.numberOfLines = 2; cell.imageView.contentMode = UIViewContentModeScaleAspectFit; cell.imageView.frame = CGRectMake(15, 6, 58, 58); cell.imageView.layer.cornerRadius = 6; cell.imageView.layer.masksToBounds = YES; Photoset * sfc = [self.myarray objectAtIndex:indexPath.row]; cell.cid = sfc.sfcid; cell.ctitle = sfc.title; cell.cimg = sfc.cover; cell.textLabel.text = sfc.title; cell.detailTextLabel.text = sfc.date; // set cell image MVImage * thumb = [[MVImage alloc] init]; NSString * retina = ([[MVProject sharedInstance] settings_retina]) ? @"2" : @""; if ([NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"Settings_SFCCovers%@_%@", retina, cell.cid]]]) { thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"Settings_SFCCovers%@_%@", retina, cell.cid]]]; [cell.imageView setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f]]; [cell bringSubviewToFront:[cell.imageView superview]]; } else { dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); dispatch_async(queue, ^{ dispatch_sync(dispatch_get_main_queue(), ^{ thumb.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@", cell.cimg]]]; thumb.title = cell.ctitle; [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:thumb] forKey:[NSString stringWithFormat:@"Settings_SFCCovers%@_%@", retina, cell.cid]]; [cell.imageView setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f]]; [cell bringSubviewToFront:[cell.imageView superview]]; }); }); } return cell; 

我应该使用SQLite数据库而不是NSUserDefaults?

我也有asynchronous加载的麻烦。 我觉得它应该是这样的:

 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); dispatch_async(queue, ^{ thumb.data = [NSData dataWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@", cell.cimg]]]; thumb.title = cell.ctitle; [[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:thumb] forKey:[NSString stringWithFormat:@"Settings_SFCCovers%@_%@", retina, cell.cid]]; dispatch_sync(dispatch_get_main_queue(), ^{ [cell.imageView setImage:[MVImage imageWithImage:[[UIImage alloc] initWithData:thumb.data] covertToWidth:58.0f covertToHeight:58.0f]]; [cell bringSubviewToFront:[cell.imageView superview]]; }); }); 

但是,这显然将错误的图像数据保存到NSUserDefault目的地。

任何帮助,我的编码风格的指针,以及其他任何东西,非常感谢。

谢谢!

只要快速浏览一下你的代码 – 你似乎将块推到asynchronous队列上,但是你正在调用这些块中的UI代码。

您应该只在主线程上运行UI代码。

至于解决scheme – 看看一些开源的实现,或者让你知道你应该做什么,或者直接使用它们。

其中之一就是Github上的AsyncImageView 。

还有其他的一些快速search会带来。

2意见build议:1.不要在NSUserDefaults中存储图像,这是更适合用户喜好,如string。

  1. 不要做两次解压操作。 只要做到这一点,然后检查结果。

replace这个:

 if ([NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"Settings_SFCCovers%@_%@", retina, cell.cid]]]) { thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"Settings_SFCCovers%@_%@", retina, cell.cid]]]; 

有了这个:

 thumb = [NSKeyedUnarchiver unarchiveObjectWithData:[[NSUserDefaults standardUserDefaults] objectForKey:[NSString stringWithFormat:@"Settings_SFCCovers%@_%@", retina, cell.cid]]]; if ( thumb ) ...