UITableViewCell 线程中的图像缓存
Posted
技术标签:
【中文标题】UITableViewCell 线程中的图像缓存【英文标题】:Image cacheing in thread for UITableViewCell 【发布时间】:2011-09-09 22:57:32 【问题描述】:我有一个图像缓存类,它将个人资料图像存储在 NSMutableDictionary 中。如果key存在,则缓存返回一个UIImage对象,如果不存在,则下载它,将其存储在字典中,并返回UIImage。这个共享缓存在 NSThreaded 方法中调用,如下所示:
[NSThread detachNewThreadSelector:@selector(setImageForUser:) toTarget:self withObject:imageUrlString];
-(void)setImageForUser:(NSString *)imageUrlString
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
LPImageCacher *imageCache = [LPImageCacher sharedCache];
UIImage *profileImg = [imageCache getCachedImageFromMemory:imageUrlString];
self.userProfileImageView.image = profileImg;
if (profileImg == nil)
imageUrlString = [[myGlobals sharedInstance].avatarUrlDefault stringByAppendingString:@"/avatar.png"];
self.userProfileImageView.image = [imageCache getCachedImageFromMemory:imageUrlString];
[pool release];
问题是,如果他们在加载任何内容之前滚动 UITableView,图像会积压,然后最终所有图像都会被加载,它们会在当前单元格上闪烁并更改,直到到达正确的单元格。我认为在每个单元格中创建一个 NSThread 实例并在 -prepareForReuse 中取消线程会很好,但我似乎无法再次重用 NSThread 对象,关于如何解决这个问题的任何想法?
【问题讨论】:
【参考方案1】:我认为您看到的问题是由于 UIScrollView 在您滚动时“冻结”所有内容。这是一个运行循环问题。为了解决这个问题,您需要确保在默认运行循环中发送 -setImageForUser:
消息。
查看这些资源以获取更多信息:
NSURLRequest won't fire while UIScrollView is scrolling
UIScrollView pauses NSTimer until scrolling finishes
希望这会有所帮助!
【讨论】:
【参考方案2】:里德奥尔森给了你直接的答案。我想提一件事。
为每个单元分配线程的成本相当高,为什么不使用NSOperationQueue?您可以有一组工作线程来执行每个单独的加载,并且将这个队列的功能限制为随时可见单元的最大数量是有意义的。这几乎是“重用线程”。
事实上,我建议使用ASIHTTP 的ASINetworkQueue。它比 NSOperationQueue 使用起来更简单。
此外,请尝试添加一个简单的优化,以便在滚动速度低于某个数字时加载单元格。当您无法停下来查看图像时,为什么还要加载图像?例如,我为 tableView 写了这样的东西:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
static float prevOffset = 0.0;
static float scrollSpeed = 0.0;
// positive -> downwards
scrollSpeed = scrollView.contentOffset.y - prevOffset;
if (scrollSpeed < 2.0)
[self loadImagesForVisibleCellsInTableView:(UITableView*)scrollView];
else if (scrollSpeed < 6.0)
shouldLoadImages = YES;
else
shouldLoadImages = NO;
prevOffset = scrollView.contentOffset.y;
这会在 tableView 快速移动时忽略加载新图像(shouldLoadImages
影响 tableView:cellForRowAtIndexPath
,告诉他们忽略加载图像)并且当它即将停止时,它会强制重新加载可见单元格。
【讨论】:
【参考方案3】:您应该使用主线程将屏幕更新给用户。这个Common multithreading mistakes beginners make on iPhone 将帮助您确定问题。
【讨论】:
以上是关于UITableViewCell 线程中的图像缓存的主要内容,如果未能解决你的问题,请参考以下文章
UITableViewCell 中的 UIScrollview 和维护滚动视图页面
UITableViewCell 上的 PFImageView 断断续续的滚动