iPhone自定义绘制UITableViewCell,如何在线程中加载+从网络插入图像?

时间:2009-11-15 17:34:42

标签: iphone objective-c uitableview uiimage drawrect

我一直在绘制自定义表格单元格(使用来自苹果的样本作为基础),现在必须做一个显示来自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个图像在表格中重复(尽管其他文本更新)。

我现在并不担心缓存,但是有没有关于如何做到这一点的样本,或者有人能指出我正确的方向吗?感谢。

5 个答案:

答案 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 ...