ios - UITableViewCell 加载图像和重复使用的单元格

标签 ios uitableview

我需要从网络/文件加载一些 UIImages。我正在搜索,我在其他 question 中找到了这段代码:

    if (![[NSFileManager defaultManager] fileExistsAtPath:user.image]) {
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,  0ul);
        dispatch_async(queue, ^{
            NSData *imageData =[NSData dataWithContentsOfURL:[NSURL URLWithString:user.imageURL]];

            [imageData writeToFile:user.image atomically:YES];
            dispatch_sync(dispatch_get_main_queue(), ^{
                UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
                UIImage *image = [UIImage imageWithData:imageData];
                [self.imageFriends setObject:image forKey:[NSNumber numberWithInt:user.userId]];
                cell.imageView.image = image;
                [cell setNeedsLayout];
                NSLog(@"Download %@",user.image);
            });
        });
        cell.imageView.image=[UIImage imageNamed:@"xger86x.jpg"];
    } else {
        NSLog(@"cache");
        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,  0ul);
        dispatch_async(queue, ^{
            UIImage *image = [UIImage imageWithContentsOfFile:user.image];
            //[self.imageFriends setObject:image forKey:[NSNumber numberWithInt:user.userId]];
            dispatch_sync(dispatch_get_main_queue(), ^{
                UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];
                newCell.imageView.image=image;
                [newCell setNeedsLayout];
            });
        });
    }

但问题是,当我快速滚动到底部或顶部时,图像加载错误,结束时会有短暂的延迟。

所以问题是.. 当我使用队列获取 UIImages 时,如何将它们加载到正确的单元格中?谢谢!

最佳答案

我怀疑您看到的不正确图像是由于您在拥有图像的本地副本但仍异步检索本地副本的情况下没有设置占位符图像的结果。此外,在您为加载本地副本而附加的代码中,您在后台线程上使用 UIImage 一个 UIKit 组件。

同样有趣的是,您似乎在进行某种UIImage 缓存。将图像添加到我假设的是名为 imageFriendsNSMutableArray 属性。但是如果您有文件的本地副本,您似乎已经注释掉了缓存添加。此外,您发布的代码从不使用缓存的 UIImages

虽然 2 级缓存似乎有点过头,但如果您想这样做,您可以这样做:

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

UIImageUIKit 的一部分,不是线程安全的。但是您可以在另一个线程上加载 NSData

关于ios - UITableViewCell 加载图像和重复使用的单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9187172/

相关文章:

ios - 如何知道应用程序运行时iPhone的时钟是否改变?

iOS6, Storyboard : UISearchDisplayController returns wrong custom UICell height

iphone - 使用 IB 加载数据的 UITableViewCell 自定义单元格

ios - swift : Pull down to dismiss `UITableViewController`

ios - 在表格 View 中第二次按下按钮时反转动画

ios - 在 SWIFT 中推送之前如何加载 View ?

ios - iOS 中的邮政编码验证

ios - Firebase 通知记录/日志 API

ios - iOS 上的表单输入样式

ios - Swift Playground 中的 lldb_expr 是什么?