我使用几乎每个人都用来处理cellForRowAtIndexPath的“着名”样板代码:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"someCustomCellID"];
if (cell == nil) // nothing to recycle from the queue: create a new cell
但这给了我很多问题'因为我的单元格包含我加载异步的图像,并且两个功能(出列和异步加载)经常发生冲突。因此,我尝试每次创建一个新单元格,并且它的工作非常好而且速度很快。 但我有一个疑问:即使我忽略返回的值并每次都创建单元格,我是否还应该调用dequeueReusableCellWithIdentifier来释放内存? 我想不再使用的单元格会被自动释放(因为它们应该是),但是我想知道缓存队列是否需要使用dequeue调用显式“free”...
答案 0 :(得分:4)
dequeueReusableCellWithIdentifier
并非旨在防止内存泄漏,但它是为性能而设计的(一种方法是减少内存使用)。使用dequeue方法时,如果有多行数据,滚动表视图会更加平滑。我建议您使用异步加载来使用dequeue方法,特别是如果您在滚动时看到任何延迟。如果您想了解如何执行此操作的示例,请参阅Apple's LaxyTableImages Example。但是,如果确实这样做,确定您不想重复使用单元格,那么在创建单元格时只需将nil
作为reuseIdentifier
传递。
答案 1 :(得分:2)
dequeueReusableCellWithIdentifier有助于减少从文件或XIB加载重新加载内容的次数。如果您有自定义单元格或具有非标准内容的单元格,则重新使用已经全部设置的单元格可以快得多。
我记得在类似的事情上工作,但在我们的例子中,我们异步地将图像加载到Core Data对象中,并让单元格观察该对象中的图像。加载图像后,会通知单元格并更新其图像视图。
当细胞通过dequeueReusableCellWithIdentifier返回给我们时,我们停止观察并将其设置为观察下一个物体的图像。
答案 2 :(得分:2)
只需在prepareForReuse:
类中使用UITableViewCell
,即可在重新使用单元格之前停止异步加载。
答案 3 :(得分:0)
是的,如果要动态分配单元格,则需要使用dequeueReusableCellWithIdentifier
来避免泄漏。
大概你的异步图像加载是这样的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell) {
...
}
NSURLRequest *request = [self URLRequestForIndexPath:indexPath];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
cell.imageView.image = [UIImage imageWithData:data];
}];
return cell;
}
该代码存在问题。在完成处理程序运行时,表视图可能已将该单元格重用于另一行!
我们需要更改完成块,以便在准备好设置图像时查找该行的单元格:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell) {
...
}
NSURLRequest *request = [self URLRequestForIndexPath:indexPath];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
if (cell)
cell.imageView.image = [UIImage imageWithData:data];
}];
return cell;
}
答案 4 :(得分:0)
您应该始终使用该方法。如果它返回一个单元格,请使用该单元格。如果它返回nil,则只有这样才能创建一个单元格。
如果该方法要求您还没有加载图像的单元格,那么您应该提供替代方法。也许UIImageView带有定制的动画进度微调器?然后,当您的图像到达时,您可以在必要时使用正确的图像。
不要担心释放细胞。一旦你将它们提供给表视图,它们就是表视图的责任(至少就内存管理而言)。