UITableViewCell load images and reused cells

后端 未结 2 916
情深已故
情深已故 2020-12-18 05:25

i need to load from web/files some UIImages. I was searching and i found in other question this code:

    if (![[NSFileManager defaultManager] fileExistsAtPa         


        
相关标签:
2条回答
  • 2020-12-18 05:43

    You are loading image asynchronously, so during fast scrolling cells get reused faster then images are downloaded. One way to avoid loading a wrong image, would be to check if cell already got reused when image is loaded. Or cancel all requests in progress when you dequeue new cells.

    I would also recommend to look at AFNetworking, as it contains helpful category for UIImageView, so you can do something like this:

    [imageView setImageWithURL:[NSURL URLWithString:@"http://i.imgur.com/r4uwx.jpg"] placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]];
    

    It also contains cancelImageRequestOperation method, to cancel requests in progress. Then your code will look like this:

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    } else {
        [cell.imageView cancelImageRequestOperation];
    }
    [cell.imageView setImageWithURL:[NSURL URLWithString:user.imageURL] placeholderImage:[UIImage imageNamed:@"xger86x.jpg"]]; 
    
    0 讨论(0)
  • 2020-12-18 05:44

    I suspect the incorrect images you see are a result of you not setting your place holder image in the event of you having a local copy of an image but still retrieving the local copy asynchronously. Also In the code you appended for loading the local copy you use UIImage a UIKit component on a background thread.

    Also interestingly you seem to be doing some kind of UIImage caching. Adding the images to what I assume is an NSMutableArray property named imageFriends. But you seem to have commented out the cache add in the event you have a local copy of the file. Also your posted code never uses the cached UIImages.

    While 2 levels of caching seems a bit overboard if you wanted to do this you could do something like this:

    UIImage *userImage = [self.imageFriends objectForKey:[NSNumber numberWithInt:user.userId]];
    if (userImage) { // if the dictionary of images has it just display it
        cell.imageView.image = userImage;
    }
    else {
        cell.imageView.image = [UIImage imageNamed:@"xger86x.jpg"]; // set placeholder image
        BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:user.image];
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            NSData *imageData = nil;
            if (fileExists){
                imageData = [NSData dataWithContentsOfFile:user.image];
            }
            else {
                imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:user.imageURL]];
                [imageData writeToFile:user.image atomically:YES];
            }
            if (imageData){
               dispatch_async(dispatch_get_main_queue(), ^{ 
                        // UIKit, which includes UIImage warns about not being thread safe
                        // So we switch to main thread to instantiate image
                   UIImage *image = [UIImage imageWithData:imageData];
                   [self.imageFriends setObject:image forKey:[NSNumber numberWithInt:user.userId]];
                   UITableViewCell *lookedUpCell = [tableView cellForRowAtIndexPath:indexPath];
                   if (lookedUpCell){
                       lookedUpCell.imageView.image = image;
                       [lookedUpCell setNeedsLayout];
                   }
               }); 
            }
        });
    }
    

    UIImages are part of UIKit and not thread safe. But you can load the NSData on another thread.

    0 讨论(0)
提交回复
热议问题