我将异步加载图像并将其设置为表格视图单元格。问题是我对单元格使用自动布局,所以我希望在设置图像后重新绘制单元格的表视图。
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300.0
通常情况下我会使用tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Fade)
,但这会调用cellForRowAtIndexPath
方法,该方法再次调用我的图片下载方法。
我尝试拨打tableView.layoutIfNeeded()
,cell.layoutIfNeeded()
,cell.setNeedsLayout()
,没有任何帮助。
我的问题是如何在不调用cellForRowAtIndexPath
方法的情况下重绘表格视图单元格?
答案 0 :(得分:2)
这里的根本问题是您下载图像的方式。您应该在代码中进行一些簿记,并跟踪哪些图像已经下载或已经下载。根据这一点,您可以决定是否应该开始新的下载。 不要试图破解这个,因为这将导致你以后很多痛苦(我从经验中知道)。 最好的方法是拥有某种数据对象,以及另一个进行下载的对象。然后,只要下载完成,此对象就会更新此图像的正确数据对象。然后这个下载器应该告诉你的dataSource这个数据对象已经更新。作为响应,您的dataSource可以重新加载该数据对象的indexPath。通过这种方式,您的dataSource永远不必担心下载,并且可以简单地检查数据对象并使用它来设置单元格上的值。如果有图像下载,它将使用它,否则没有图像(或某些占位符可能)。
现在,您可以将包含@(YES)或@(NO)的字典属性作为键的值或单元格的名称或indexPath保存为键。然而,这种方法很幼稚,因为它不会非常易于维护或移植(对于其他viewControllers或应用程序的部分),并且indexPath和image之间没有简单的转换。请记住,tableViewCells永远不能用作使用某些逻辑的数据源:它们是您拥有其他逻辑的终端点。这是因为它们被重复使用,并且基本上不可信任在某个位置。基于indexPaths所做的一切。 (并使用tableview获取单元格的indexPath。)
所以,现在你可以在cellForRowAtIndexPath:
NSString * imageURL = ....
NSNumber * downloading = self.imageDownloads[imageURL];
if (!downloading.boolValue)
{
self.imageDownloads[imageURL] = @(YES);
// start your download
}
- (void) imageDownloadedForURL: (NSString *) imageURL
{
self.imageDownloads[imageURL] = @(YES); // this is redundant
[self.tableView reloadRowAtIndexPaths: @[indexPathForThisImage]];
}
- (void) imageDownloadForULRFailed: (NSString *) imageURL
{
self.imageDownloads[imageURL] = @(NO);
// trigger a new download? (but be careful not to DDOS your server this way)
}
答案 1 :(得分:0)
如果您使用UIImageView
显示图片,则无需重新绘制单元格,只需在图片下载完成后设置图片属性即可。
如果您自己在自定义UIView
子类上绘制图像,则可以在该视图上调用setNeedDisplay
方法,该方法将视图标记为脏,并在下一个周期重绘。 / p>
但是,最好的方法是改进cellForRowAtIndexPath:
并在模型对象中设置downloading
标志,并且仅在未设置该标志时才开始下载。