我一直在绘制自定义表格单元格(使用来自苹果的样本作为基础),现在必须做一个显示来自URL的图像的单元格 - 每个单元格都有不同的图像(基于某些它拥有的数据)但是所有的单元都是相同的,因此重用的id相同。
这样做的正确结构是什么?显然我需要在新线程中加载图像。到目前为止,我有以下函数坐在单元格视图类中,该类在自己的线程中运行:
- (void)loadImage
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
self.img = [UIImage imageWithData: [NSData dataWithContentsOfURL: [NSURL URLWithString: [myProduct objectForKey:@"ImagePath"]]]];
[self setNeedsDisplay];
[pool release];
}
当我从drawRect函数本身(这是坏的)调用它时,它“工作”,但这显然会在每次发生任何事情时被调用(选择等)。如果我将它放在单元格uiview的init函数中,那么它只会被调用前8个单元格,然后它们会被重用。其他变化最终导致图像在重复使用时不会“重置”,因此相同的8个图像在表格中重复(尽管其他文本更新)。
我现在并不担心缓存,但是有没有关于如何做到这一点的样本,或者有人能指出我正确的方向吗?感谢。
答案 0 :(得分:2)
解决方案必须更加复杂,因为默认情况下UITableView会循环使用单元格(当一个滚动从顶部滚动时,它会移动到底部并使用新数据重新配置)。因此,您可能会开始下载图像,但在下载完成之前会更改单元格的内容。
在cellForRowAtIndexPath:
中,您应该从缓存中获取图像(myProduct对象,NSArray,等等)。如果它不在那里,你应该检查一个标志,看它是否已被加载。如果尚未加载,则设置该标志并分离新线程(您应该查看NSOperation
,它将排队工作并保护您不会一次启动太多线程)。
在你的主题中,你应该下载图像,然后使用performSelectorOnMainThread:target:waitUntilDone:
在图像的主线程上调用方法。该方法可以更新缓存,将isLoading标志设置为NO,并更新单元。这样做非常重要,因为Cocoa要求所有UI更新代码都在主线程上。
我希望这是一个有用的概述。
答案 1 :(得分:1)
如果你还没有看到Apple的明确文档,说明UIImage是线程安全的,我认为你不应该这样做。而是将您的图像作为NSData并将其转换为主线程中的UIImage。基本规则是所有UIKit工作必须在主线程中完成或行为未定义。
答案 2 :(得分:1)
这应该回答您的问题。LazyTableImages
答案 3 :(得分:0)
好吧,当您将单元格出列时,可以强制将图像加载到那里。您不必在init中执行此操作...通常您执行:
cell = dequeueCell...
if (!cell) {
//create one
}
return cell;
您可以做的是在返回单元格之前,如果它是您想要的单元格类型,则可以强制加载图像。这样,无论何时显示,您都可以从缓存中获取它(如果存在),如果不存在,则转到Web上。
答案 4 :(得分:0)
查看stanford讲座中的相应幻灯片/视频/代码示例cs193p ... iphone application programming ...