我对UITableView单元格渲染的正确行为感到非常困惑。情况如下:
我有一个250个项目的列表,这些项目正在加载到表格视图中,每个项目都有一个图像。为了优化图像下载,我跟着Apple的LazyTableImages示例代码...几乎完全遵循它。非常好的系统......作为参考,这里是Apple示例代码中的单元格渲染器:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// customize the appearance of table view cells
//
static NSString *CellIdentifier = @"LazyTableCell";
static NSString *PlaceholderCellIdentifier = @"PlaceholderCell";
// add a placeholder cell while waiting on table data
int nodeCount = [self.entries count];
if (nodeCount == 0 && indexPath.row == 0)
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:PlaceholderCellIdentifier] autorelease];
cell.detailTextLabel.textAlignment = UITextAlignmentCenter;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.detailTextLabel.text = @"Loading…";
return cell;
}
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
// Leave cells empty if there's no data yet
if (nodeCount > 0)
{
// Set up the cell...
AppRecord *appRecord = [self.entries objectAtIndex:indexPath.row];
cell.textLabel.text = appRecord.appName;
cell.detailTextLabel.text = appRecord.artist;
// Only load cached images; defer new downloads until scrolling ends
if (!appRecord.appIcon)
{
if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
{
[self startIconDownload:appRecord forIndexPath:indexPath];
}
// if a download is deferred or in progress, return a placeholder image
cell.imageView.image = [UIImage imageNamed:@"Placeholder.png"];
}
else
{
cell.imageView.image = appRecord.appIcon;
}
}
return cell;
}
所以 - 我对Apple的LazyTableImages系统的实现有一个至关重要的缺陷:它立即启动所有图像的所有下载。现在,如果我删除这一行:
//[self startIconDownload:appRecord forIndexPath:indexPath];
然后系统的行为与您期望的完全相同:新图像在其占位符滚动到视图时加载。但是,初始视图单元格不会在单元格渲染器中没有该提示的情况下自动加载其图像。所以,我有一个问题:通过单元格渲染器中的提示,所有图像立即加载。如果没有提示,则不会加载初始视图。现在,这在Apple示例代码中运行良好,这让我想知道我的情况如何。它几乎就像是在前面构建所有单元而不是仅仅显示在显示器内的8个左右。所以,我调查了一下,事实确实如此......我的桌子正在建造250个独特的细胞!我不认为UITableView是这样工作的,我想我认为它只构建了填充表所需的项目。是这种情况,还是预先建立所有250个单元格是否正确?
另外 - 相关问题:我试图将我的实现与Apple LazyTableImages示例进行比较,但发现在Apple示例代码中似乎禁用了NSLog(这使得直接行为比较非常困难)。这只是一个简单的发布设置,还是苹果以某种方式锁定了他们的样本,以便您无法在运行时记录输出?
谢谢!
答案 0 :(得分:1)
您当然不应该为表中的每一行都有一个实际的UITableViewCell实例。您应该只看到比UI中可见的更多实例。这就是你的问题所在。它与加载图像没有任何关系。
我唯一一次看到大量细胞在出列的细胞实例化的时候是编码器改变了tableview的框架,使其比屏幕大得多。无论可见什么,桌面视图都会保留足够的单元格,使其不会出现在自己的框架上。如果帧很大,那么你会在队列中获得大量的单元格。
NSLog确实可以在Apple示例中使用,因此如果您无法获得NSLog输出,那么开发工具本身就会发生奇怪的事情。
你可能想要关闭Xcode和模拟器并重新启动,看看是否能清除奇怪的行为。
答案 1 :(得分:1)
哦,我的... mustISignUp绝对正确地说“你肯定有更深层次的根本问题”。我有可变高度的表行,我正在对行本身进行所有高度计算和数据存储,而不是在填充它们的数据模型上。结果,我的heightForRowAtIndexPath方法正在创建并填充所有单元格,该方法正在从单元格对象中读取单元格高度。所以 - 经验教训。
感谢mustISignUp,我喜欢你的用户名。
答案 2 :(得分:0)
Apple示例代码中未禁用NSLog。我不知道为什么你看不到它,但你肯定有更深层次的根本问题。
无论如何,为了比较: - 如果屏幕上有6行 -tableView:cellForRowAtIndexPath:被调用6次,索引为[0,0] - [0,5]。
那么,你看到的是什么? -cellForRowAtIndexPath被调用了多少次?