如果在 UITableView
中找到,我必须从地址簿中获取联系人并在每个联系人旁边显示照片。
我使用 ABContactsHelper
库获取所有联系人,然后使用 GCD block 异步获取 UITableView
中可见行的照片。
我提到了一个 Apple 示例代码,它等待 UITableView 完成滚动,获取可见的 NSIndexPath
并创建线程来获取照片。到目前为止,我的问题有两个。
首先,如果用户滚动、停止、滚动并停止并执行多次,则会生成太多线程来获取照片,这会降低应用程序的速度。
其次,当线程返回以在缓存中设置照片以及 UITableViewCell
时,对 UIImageView
的引用现在被重用于 中的另一条记录UITableViewCell
,因此照片被放置在错误的记录上,当该特定记录的线程返回时,该记录最终会被正确的记录替换。
这是我在 cellForRowAtIndexPath
以及 UITableView
停止滚动时使用的代码。
- (void)loadImagesLazilyForIndexPath:(NSIndexPath *)indexPath photo:(UIImageView *)photo contact:(ContactModel *)contact
{
if (!self.tableView.isDragging && !self.tableView.isDecelerating) {
UIImage *thePhoto = [self.imagesForContacts objectForKey:indexPath];
if (!thePhoto) {
// NSLog(@"Photo Not Found - Now Fetching %@", indexPath);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
@autoreleasepool {
UIImage *image = [[JMContactsManager sharedContactsManager] photoForContact:contact];
if (!image)
image = self.noProfilePhoto;
[self.imagesForContacts setObject:image forKey:indexPath];
dispatch_async(dispatch_get_main_queue(), ^{
// NSLog(@"Photo Fetched %@", indexPath);
@autoreleasepool {
NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
BOOL visible = [visiblePaths indexOfObjectPassingTest:^BOOL(NSIndexPath * ip, NSUInteger idx, BOOL *stop) {
if (ip.row == indexPath.row && ip.section == indexPath.section) {
*stop = YES;
return 1;
}
return 0;
}];
if (visible)
photo.image = [self.imagesForContacts objectForKey:indexPath];
[[NSURLCache sharedURLCache] removeAllCachedResponses];
}
});
}
});
} else {
// NSLog(@"Photo Was Found %@", indexPath);
@autoreleasepool {
photo.image = [self.imagesForContacts objectForKey:indexPath];
}
}
}
}
最佳答案
对于这种功能,我会选择 NSOperation 和 NSOperationQueue,它们构建在 GCD 之上,但它为您提供了取消操作的机会。您可以检查哪些操作不再可见并取消它们。通过这种方式,您可以控制引用“离开”。
我还看到另一个可能导致“问题”的问题,您似乎正在 NSMutableDictionary 中缓存图像,不是吗?或者你在使用 NSCache?如果它是一个 NScache 就很好,但是大多数可变对象“自然”不是线程安全的
提高队列的优先级:-)
关于iphone - 多线程在获取照片时使用 GCD,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16330825/