UITableViewCell cellForRowAtIndexPath 首次滚动时调用大量行
Posted
技术标签:
【中文标题】UITableViewCell cellForRowAtIndexPath 首次滚动时调用大量行【英文标题】:UITableViewCell cellForRowAtIndexPath calling large number of rows when first scrolling 【发布时间】:2010-10-27 23:47:42 【问题描述】:我一直在研究与 UITableView 和 cellForRowAtIndexPath 相关的问题。
我想让用户能够拥有非常多的行,就像 iPhone 上的大型电子邮件列表一样。当我开始创建一个类时,我发现了这个问题,该类将根据需要从数据库中排队和出列记录组,以节省内存。我发现当我的 UITableViewController 加载时,它会为典型的前 10 个索引(0 到 9)调用 cellForRowAtIndexPath。当我在模拟器的黑色外表面区域单击鼠标或尝试使用向上手势在 UITableView 上向下滚动时,就会出现问题。此时,为所有剩余索引调用 cellForRowAtIndexPath。即使有 1000 多个单元格,也会发生这种情况。我试图用只有 100 个索引(没什么花哨的)重新创建一个非常简单的项目。它做的事情完全一样。当我滚动时,它会从位置 10 到 99 调用 cellForRowAtIndexPath。
这是 UITableView 的正常行为吗?有谁知道为什么它调用所有行的效率低下?
我会说,一旦这个初始阶段发生,它似乎就开始正常工作了。我对此感到非常困惑,因为它几乎不可能根据需要创建一个用于排队和取消排队记录的类。
这是我的简单得多的示例项目的代码:
// Customize the number of sections in the table view.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
return 1;
// Customize the number of rows in the table view.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
return 100;
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
printf("RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = %d\n", indexPath.row);
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.textLabel.text = @"Example Text";
return cell;
控制台:
…… 视图的初始加载 ......
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 0
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 1
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 2
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 3
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 4
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 5
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 6
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 7
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 8
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 9
…… 第一个滚动手势 ......
ootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 11
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 12
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 13
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 14
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 15
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 16
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 17
。 . 我在这里删除了一些以缩短它 . .
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 97
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 98
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 99
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 10
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 11
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 12
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 13
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 14
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 15
RootViewController, -tableView:cellForRowAtIndexPath; // indexPath.row = 16
(gdb)
感谢您的帮助。
埃里克
编辑(后天)--> 今天我想尝试一个真实的设备而不是我的模拟器。我的 iPhone 3GS 没有重现这种奇怪的行为。我相信我机器上的模拟器可能有问题。我打算在时间允许的时候尝试另一个 MAC。
【问题讨论】:
【参考方案1】:这个问题的原因是我在我的 Mac 上安装了一个名为 Cinch 的应用程序。
Cinch 是一个窗口管理应用程序,它为 Mac OS 添加了一个窗口“捕捉”功能。否则该程序效果很好。每当我使用 cellForRowAtIndex 路径时,我只需要记住禁用 Cinch。
遗憾的是,我不得不重新加载我的整个计算机才能解决这个问题!希望这对其他遇到这种奇怪功能的人有所帮助。
【讨论】:
非常感谢您的回答。我被困在完全相同的问题上,也使用 Cinch。你为我节省了很多浪费的时间。 你是我的英雄!我永远不会想到这一点。非常感谢。 @geekinit 请选择你的答案 哇!非常感谢!有人通知 Cinch 的开发者吗? @Klaas,我在你回复的时候向 Cinch 报告了这件事。他们说他们正在努力。与此同时,我已经养成了在菜单栏中禁用和启用它的习惯。 ://【参考方案2】:以防万一有些人有同样的奇怪问题并且没有安装像chinch这样的程序:如果您不使用真正单独的单元格标识符,则会发生相同的行为..如果您只使用苹果示例中的标准标识符,那么它就不起作用了。
每次滑动表格视图时,都会有条目旋转。您必须使每个单元格的单元格标识符都是唯一的。例如:
NSString *CellIdentifier = [NSString stringWithFormat:@"Cell%d", indexPath.row];
我花了一段时间才弄明白。所以如果有人在寻找“uitableview uitableviewcell 奇怪的行为行切换触摸幻灯片上的内容”时发现这个线程,他可以检查这个可能的错误源。
【讨论】:
我认为您错过了单元重用机制的全部要点。当一个单元格离开屏幕时,它会进入重用队列,以便可以再次与另一个索引路径一起使用。这样,同一个单元格对象可以通过dequeueReusableCellWithIdentifier
用于多行(出于性能原因)。因此,无需实例化大量单元格,您只需实例化所需数量的单元格,即尽可能多的可见单元格。如果你给每个单元格一个唯一的重用标识符,那么你根本就没有重用你的单元格。
hmm...那么请告诉我,我应该如何用数据填充我的单元格?我在 cellForRowAtIndexPath 方法中执行此操作。我为对应的行创建单元格并添加带有数据的标签。当单元格不在视线范围内时,会分配其他单元格并填充数据。如果用户再次向上滚动到第一个单元格,它将从 dequeueReusableCellWithIdentifier 方法中出列。因此,当再次显示时,每个单元格都会被重复使用。否则你会怎么做?只有一个内容不断变化的单元格对象?
好的,我再次测试了它.. 看来,我错了 - 它现在似乎真的有效。也许我的代码中有其他问题,目前已经消失了..
这样你就使用了一个只有一行的单元格对象。这样,您需要与表格视图中的行一样多的单元格。单元重用机制允许您重用具有多行的一个单元对象。当一个单元格离开屏幕时,它可以用来显示另一行。如果滚动表格视图时您的行混淆是因为您在重用单元格时没有清除“旧”内容
真的应该删除这个答案。【参考方案3】:
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:nil];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease];
将此 nil 用于重用标识符,使其正常工作
【讨论】:
以上是关于UITableViewCell cellForRowAtIndexPath 首次滚动时调用大量行的主要内容,如果未能解决你的问题,请参考以下文章
使用 UITapGestureRecognizer 检测 UITableViewCell 中 UILabel 的点击事件
如何在横向上调整自定义 UITableView 分隔符并防止消失
numberOfRowsInSection 多次调用但 cellForRowAtIndexPath 从未调用
未调用 alertviewcontroller 中的 tableview 的“cellForRowAtIndexPath”