【问题标题】:tableView:dequeueReusableCellWithIdentifier issues with "global" constanttableView:dequeueReusableCellWithIdentifier 问题与“全局”常量
【发布时间】:2014-10-20 10:03:53
【问题描述】:

请保存我的头发或指出我的(明显)错误。我正在尝试在子类 UITableViewController 中使用 UITableViewCellStyleSubtitle 的 UITableViewStyle。

我在实现中定义了一个静态常量:

static NSString * const kAHCellIdentifier;

viewDidLoad我注册了一个tableView类:

[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kAHCellIdentifier];

然后在tableView:cellForRowAtIndexPath 中初始化单元格如下:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kAHCellIdentifier];
if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kAHCellIdentifier];
}

运行应用程序(设备或 sim)时,单元格会加载,但没有显示 detailTextLabel,但是如果我这样初始化,它可以正常工作*

我的猜测是该常量实际上并不是静态的,或者存在错误(8.0.2),或者由于缺乏睡眠或其他原因,我完全丢失了某些东西。

还可以指出,如果我不注册该类,则会出现编译器错误(预期),但即使单元格标识符不同(我猜这是预期的,因为我可以为不同的注册不同的类)单元格样式。

我错过了什么?

编辑

使用[tableView dequeueReusableCellWithIdentifier:kAHCellIdentifier forIndexPath:indexPath]; 也无效。

简短的问题

如果我在 cellForRowAtIndexPath 方法调用中使用静态 NSString,而不是,如果我使用类级全局常量,为什么 dequeueReusableCellWithIdentifier 返回 nil 并因此使用 cell == nil 块中的 UITableViewCellStyle 启动单元格如上所述。

附加

更多的测试产生了一些不同的结果。如果您为单元重用标识符注册一个类,然后在cellForRowAtIndexPath 中为单元提供不同的标识符,那么它可以工作。如果你给它的名字和注册的类一样,那么它就不能按预期工作。

回答

经过一些测试和@MANIAK_dobrii 的回答,有些清晰。

如果您想使用较新的单元格出队方法dequeueReusableCellWithIdentifier:forIndexPath 并需要使用UITableViewCellStyle 而非默认值,则需要继承UITableViewCell 并覆盖initWithStyle 方法调用中的tableview 样式。

如果您乐于使用旧方法,请确保您没有为重用标识符注册类,否则它将无法工作。

【问题讨论】:

  • @joe 为什么在我的问题上显示被拒绝的编辑,实际上它改变了问题的基础?

标签: ios objective-c xcode uitableview


【解决方案1】:

这很有趣,因为我刚刚在文档中找到了 dequeueReusableCellWithIdentifier: 的新段落,我上次没有看到那里:

如果您为指定的标识符和新单元格注册了一个类 必须创建,此方法通过调用其初始化单元格 initWithStyle:reuseIdentifier: 方法。对于基于笔尖的单元格,这 方法从提供的 nib 文件加载单元对象。如果 现有单元格可供重用,此方法调用单元格的 prepareForReuse 方法。

这是否意味着如果你注册了一个类,即使dequeueReusableCellWithIdentifier: 在重用队列中不可用时也会尝试创建单元格并始终返回一个有效的单元格?由于-dequeueReusableCellWithIdentifier:forIndexPath: 可用,我只使用它。所以,我猜你的

if (cell == nil) {
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}

永远不会被调用,你最终会得到通过

创建的单元格
[[registred_class alloc] initWithStyle:STANDARD_STYLE reuseIdentifier:registred_reuse_identifier];

同时,你已经说过,如果你不注册类,你会得到编译时错误,这很奇怪,你不应该得到任何错误。

所以,我的解决方案是:
1. 不要通过-registerClass:forCellReuseIdentifier: 注册单元类并使用-dequeueReusableCellWithIdentifier: 来获取重用单元或创建它们,就像你现在正在做的那样。再一次,使用老派的方法,你不注册任何东西,如果有就出队,如果没有就创建。

// I've put it here just for a clarification that that's doesn't matter for the case
static NSString *const cellID = @"CellID";
// Just this, do not register anything, cell should get the same id as you ask
// i.e. you should init cell with the same id you then try to dequeue
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
    if(!cell)
    {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellID];
    }

    cell.textLabel.text = @"Title";
    cell.detailTextLabel.text = @"subtitle";

    return cell;
}

或:
2. 创建 nib,在其中放置一个 UITableViewCell,使其样式为 UITableViewCellStyleSubtitle,并将该 nib 注册为重用标识符,而不是使用 registerNib:forCellReuseIdentifier: 的类。

另外,请确保您正确设置了所有标题/颜色/透明度,这样您就不会只将空字符串或 nil 设置为单元格上的标签。

【讨论】:

  • 出队的单元格永远不会返回 nil,所以正如您正确假设的那样,永远不会调用 cell == nil 块。我似乎不明白的是,为什么如果我使用在 cellForRowAtIndexPath 调用中调用的静态 NSString 单元标识符,而不是使用具有类级别全局常量的相同 dequeue 调用(上面更新了问题)。
  • @ByronRode 不确定是什么原因造成的(即将声明移动到文件级别,但它不起作用,此外,如何?发生了什么变化?它崩溃了还是什么?)。也许有一些愚蠢的东西,比如错字、不同的变量或被遗忘的行打破了这一切(通常没有魔法,问题就是这样)。或者该文件级声明行可能在不同的文件中,并且存在一些编译器配置错误。所以,从外部的角度来看,如果你只使用 oldschool ~deqCellWithId: 和全局 cellID 应该没有什么不好。你可以从头开始,看看它是否有效。
  • 见上面我的附加编辑。如果类和单元格中的重用标识符相同(很奇怪,正确),则它不起作用,但如果单元格和类不同。
  • 如果使用旧的 dequeueReusableCellWithIdentifier: ,为什么还要注册类? dequeueReusableCellWithIdentifier:atIndexPath: 需要注册类(或 nib),因此它始终可以返回一个有效的单元格,使用注册的类或从注册的 nib 创建它。问题是您注册了一个课程,而您不需要。
  • @ByronRode 如果您不想对任何东西进行子类化,我还提出了第二种解决方案,可以很好地与新方法一起使用。但是我建议使用旧方法,如果你必须做这么多(子类,注册),如果你可以添加两三行来创建一个单元格,如果队列中没有可重复使用的单元格,那么你不会看到太多利润。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多