Objective C Custom Lazy Load Images UITableView Cell

笑着哭i 提交于 2019-11-28 09:55:46

问题


First time loading remote images into an iPhone app, and would like some help optimizing the process. What I've currently done is get the image if it doesn't exist, and cache it. The major goals are to:

  • only load images when needed.
  • save images for future use to reduce data consumption, and allow the user to have a somewhat functional app when not connected to the internet.

I just don't think I'm doing it well enough.

Here's a snippet of the code within 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;

Should I use a SQLite database instead of NSUserDefaults?

I'm also having trouble with the asynchronous loading. I feel like it's supposed to look like this:

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]];
    });
});

But that obviously saves the wrong image data to the NSUserDefault destination.

Any help on this, pointers on my coding style, and anything else is greatly appreciated.

Thanks!


回答1:


Just having a quick look at your code - you seem to be pushing blocks onto asynchronous queues, but you are calling UI code in those blocks.

You should only run UI code on the main thread.

As for a solution - have a look at some of the open source implementations to either give you an idea of what you should be doing, or just use them directly.

One such is AsyncImageView on Github.

There are others that a quick search will bring up.




回答2:


2 suggestions: 1. Don't store images in NSUserDefaults, that is more suitable for user preferences, like strings.

  1. Don't do the unarchive operation twice. Just do it, then check the results.

Replace this:

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]]];

With this:

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


来源:https://stackoverflow.com/questions/9083454/objective-c-custom-lazy-load-images-uitableview-cell

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!