了解UITableView dequeueReusableCellWithIdentifier - 即使在第一次调用时也返回单元格

时间:2013-06-18 19:11:00

标签: ios objective-c uitableview

我无法理解其工作原理。我已经阅读了很多有关它的帖子 - 例如UITableView dequeueReusableCellWithIdentifier TheoryHow does dequeueReusableCellWithIdentifier: work?

但是,我的UITableView每次都会成功地将一个单元格出列(它永远不会为零),即使它首次加载也是如此。我的印象是类似的单元格应该使用相同的标识符,因此您只需要更改必要的内容。

由于

if (!cell) {
    NSLog(@"New cell");
    cell = [[UITableViewCell alloc] initWithStyle:someStyle reuseIdentifier:someIdentifier];
}

永远不会被调用,我不确定我应该如何处理具有不同样式的同一个表中的单元格,因为该样式只能在初始化程序中设置。

我还尝试使用不同的单元格标识符,以确保它不会重用来自不同表格或其他内容的单元格。我正在使用[tableView registerClass: forCellReuseIdentifier:]

注册这些标识符

如果我理解,这种方法应该只返回已经移出屏幕的先前创建的单元格(隐藏,即可以重复使用)。那么为什么它第一次被调用时会返回一个单元格呢?


编辑:所以混淆是使用[tableView dequeueReusableCellWithIdentifier: forIndexPath:]而不是[tableView dequeueReusableCellWithIdentifier:](第一个需要注册标识符,第二个将返回nil,如果没有可用的话 - 行为我期待以上)。

但是,我注意到当我将代码更改为使用[tableView dequeueReusableCellWithIdentifier:]时,它会创建一个新单元格,其contentView.frame的宽度为320(全宽)。之前,当我做dequeue...forIndexPath时,它会给出302的宽度,或者单元格的视觉/“实际”宽度。这是为什么?

另外,有没有办法指定重新注册的UITableViewCells的样式?


解决方案:所以我找到了这个帖子UITableView cell.contentView.bounds.size.width Changes With Cell Reuse,它说当你将自动调整掩码设置为UIViewAutoresizingFlexibleLeftMargin时,它会在你尝试进行相对定位时修复(contentView宽度最初是完全的)宽度,但当你呈现它缩小时,所以如果你做正确的计算,它仍然会正确显示。

我正在将UISwitch定位在右侧 - 当我设置自动调整遮罩时,它在第一次显示时工作,但在我切换时移动了另外~20个像素。我不知道是什么造成了这个额外的转变,但我最后通过简单地将UISwitch设置为单元的附件视图来解决它。

(这是原始问题的部分偏离主题,但如果有人偶然发现它可能会有用)。对于任何想知道原始问题的人来说,答案都在第一次编辑之下。

4 个答案:

答案 0 :(得分:9)

当您致电[tableView registerClass: forCellReuseIdentifier:]时,您正在教授表格视图,以便您稍后使用指定的ReuseIdentifier时该怎么做。因此,当您稍后致电[tableView dequeueReusableCellWithIdentifier:]时,它将会:

一个。获取之前已创建且当前未使用的单元格

OR

B中。创建您指定的类的新单元格

所以,当你出队时,你总会得到一个实例。如果要使用initWithStyle:reuseIdentifier:自己创建新的单元格实例,则不应使用表格视图注册类。或者,保留注册并添加逻辑以指定需要配置的所有内容(并考虑使用多个不同的单元类并重用标识符)。

答案 1 :(得分:0)

因为第一次单元格为零,这就是调用它的原因:

if (!cell) {
NSLog(@"New cell");
cell = [[UITableViewCell alloc] initWithStyle:someStyle reuseIdentifier:someIdentifier];
}

但是如果单元格已经准备好重用并且基本上它不是nil - 它返回单元格并且它不会触及上面的if语句

答案 2 :(得分:0)

来自https://developer.apple.com/library/ios/#documentation/UIKit/Reference/UITableView_Class/Reference/Reference.html#//apple_ref/doc/uid/TP40006943

的苹果文档
  

当系统要求为表视图提供新单元格时,请从数据源对象中调用此方法。如果现有单元格可用,则此方法会使现有单元格出列,或者使用先前注册的类或nib文件创建新单元格。如果没有单元可供重用,并且您没有注册类或nib文件,则此方法返回nil。

出队方法

  1. 返回已回收的单元格(如果有的话)

  2. 如果您注册了一个,则创建一个新单元格(您提到过这样做了)

  3. 如果这些都不成立,则返回nil

  4. 我猜你是否删除了注册(可能隐藏在xib中),那么你将获得nil结果。

答案 3 :(得分:-1)

如果你看到UITableView.h

从iOS 6开始,客户可以为每个单元注册一个笔尖或类。

如果注册了所有重用标识符,请使用较新的 - dequeueReusableCellWithIdentifier:forIndexPath:以保证返回单元格实例。

从新的dequeue方法返回的实例在返回时也会正确调整大小。

(void)registerNib:(UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);

(void)registerClass:(Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);