我需要从网络/文件加载一些 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
缓存。将图像添加到我假设的是名为 imageFriends
的 NSMutableArray
属性。但是如果您有文件的本地副本,您似乎已经注释掉了缓存添加。此外,您发布的代码从不使用缓存的 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];
}
});
}
});
}
UIImage
是 UIKit
的一部分,不是线程安全的。但是您可以在另一个线程上加载 NSData
。
关于ios - UITableViewCell 加载图像和重复使用的单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9187172/