UITableViewCell选择器setSelected:animated:被多次调用?

我在自定义的UITableViewCell类中发现了setSelected:animated:一个奇怪的行为。 我发现如果单击表格中的单元格,会多次调用此函数。 我想知道这是正常行为还是我的代码中的错误。

为了帮助调试,我在我的自定义UITableViewCell类实现中修改了setSelected:animated: function,如下所示:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; // Configure the view for the selected state. if (selected) NSLog(@"Yes %X", &self); else NSLog(@"No %X", &self); } 

如果我单击模拟器中的单元格,这是我在控制台中获得的内容:

 2011-03-22 22:05:26.963 marketPulse[3294:207] Yes BFFFDDD0 2011-03-22 22:05:26.964 marketPulse[3294:207] Yes BFFFDE30 

你会认为我只能获得1个条目,因为我只点击了1个单元格。

如果我在那之后点击另一个单元格:

 2011-03-22 22:07:11.014 marketPulse[3294:207] No BFFFD890 2011-03-22 22:07:11.016 marketPulse[3294:207] No BFFFDD00 2011-03-22 22:07:11.017 marketPulse[3294:207] Yes BFFFDDD0 2011-03-22 22:07:11.017 marketPulse[3294:207] Yes BFFFDE30 

如果我连续两次点击同一个单元格,我会得到2个以上是的

 2011-03-22 22:08:41.067 marketPulse[3294:207] Yes BFFFDDD0 2011-03-22 22:08:41.068 marketPulse[3294:207] Yes BFFFDE30 2011-03-22 22:08:41.069 marketPulse[3294:207] Yes BFFFDE30 

我点击相同单元格的次数越多,我会得到的就越多,如果我之后点击不同的单元格,我会得到很多

我在NSLog之前放了一个断点,看着调试器,似乎所有重复的调用都是来自同一个对象。

这是我的tableView:cellForRowAtIndexPath:函数的一部分,这样你就可以看到我的单元格是如何被处理的:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *ContentCellIdentifier = @"newsTableCellContent"; UITableViewCell *cell; //index of cell data in tableData NSUInteger index = indexPath.row / 2; ... //content of story else if( [indexPath row] % 2 == 1 ) { cell = [tableView dequeueReusableCellWithIdentifier:ContentCellIdentifier]; if (cell == nil) { NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"newsTableCells" owner:nil options:nil]; for (id currentObject in topLevelObjects) { if ( [currentObject isKindOfClass:[newsTableCellContent class]] ) { cell = currentObject; break; } } } ((newsTableCellContent *)cell).content.text = [[tableData objectAtIndex:index] description]; } return cell; } 

一切正常,所以很难判断重复调用setSelected:animated:是有意还是无意。 如果这是正常操作,我可以用另一种方法做,但我想知道是否发生这种情况。

谢谢

发生的事情只是UITableView跟踪表中选择的单元格。

由于在滚动大型表视图时会重复使用单元格,因此表格视图必须将所选单元格的列表分开。 不仅如此,但每当它重用一个单元格时,它必须设置其选定的属性,因为它可能使用了之前化身中旧的无效selected状态。

当您点击一个单元格时,会发生以下几种情况:取消选择先前选择的单元格(使用setSelected: 。 新单元格突出显示。 它被去突出显示(至少如果您点击,而不是按住手指),并且setSelected:方法,因为选择了新单元格。 那是一个。

第二个调用是延迟执行调用,可能来自表视图尚不知道表的最终状态是什么的点。 此调用转到_selectAllSelectedRows ,顾名思义,它在所有选定的行上调用’setSelected:animated:’。 那是第二次通话。 其原因很可能是由于表视图处于“转换”状态而解决潜在问题,但谁知道。

是否是一个错误是解释。 重复调用的修复方法是:

 if (self.selected == selected) return; 

在调用super之前(如果self.selected == selectedself.selected == selected调用super)。

如果您使用的是iPad,这是正常现象。 (它只在iPhone上调用一次)。

为了停止获得多个“setSelected:YES”或多个“setSelected:NO”,您所要做的就是:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; } 

现在,1点击任何单元格给你:

  • setSelected的1个条目:YES动画:NO
  • tableView的1个条目:didSelectRowAtIndexPath:
  • setSelected的1个条目:NO animated:YES

因此,无论您做什么,呼叫现在都是稳定的。

理想情况下,您不应该从代码中的任何位置调用setSelected。 UIKit将负责调用它。

如果要在cellForRowAtIndexPath方法中显示一个单元格/行,只需调用即可

 tableView.selectRowAtIndexPath(indexPath, animated: true, scrollPosition: .None) 

对于那个特定的indexPath。

除非你真的想要,否则永远不要明确地调用setSelected。

当滚动表时,绝对应该调用它。 单元格被重用,这意味着,如果你在不可见区域滚动单元格将被重用和重新初始化,包括调用setSelected,它基本上是一个轻量级的属性设置器。

如果你真的想看看发生了什么,可以在tableView:cellForRowAtIndexPath:中添加一个NSLog,它将记录indexPath和返回的单元格。

整个日志应该让您很好地理解内部和内部发生的事情。 我想它会是这样的(点击IndexPath 1:1)

在1:0(先前选择的单元格)上给我单元格。
取消选择1:0
再次给我1:0的单元格(取消选择后更新)
取消选择1:0(更新此单元格上的选定标记并触发动画)
按1:1给我单元格
选择1:1
再次按1:1给我单元格(选择后更新)
选择1:1(更新此单元格上的选定标记并触发动画)

再次单击选定的单元格只是略有不同 – 它不会触发取消选择,而是触发另一个更新。