Objective C自定义延迟加载图像UITableView单元格

时间:2012-01-31 16:48:23

标签: iphone objective-c ios uitableview lazy-loading

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

  • 仅在需要时加载图片。
  • 保存图片以备将来使用以减少数据消耗,并允许用户在未连接到互联网时拥有功能稍强的应用程序。

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

以下是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吗?

我也遇到了异步加载问题。我觉得它应该是这样的:

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目的地。

对此有任何帮助,关于我的编码风格的指示以及其他任何内容都非常感谢。

谢谢!

2 个答案:

答案 0 :(得分:5)

只需快速查看代码 - 您似乎将块推送到异步队列,但是您在这些块中调用UI代码。

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

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

Github就是AsyncImageView

还有其他人会提出快速搜索。

答案 1 :(得分:2)

2条建议:  1.不要将图像存储在NSUserDefaults中,这更适合用户首选项,如字符串。

  1. 不要进行两次unarchive操作。只需这样做,然后检查结果。
  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]]];
    

    有了这个:

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