[cell viewWithTag:] 中的标签始终返回为 nil

Label in [cell viewWithTag:] is always returned as nil

我为这个基本的事情苦苦挣扎了一天多,这让我发疯!有趣的是,我在其他屏幕上也有非常相似的东西,而且效果很好!我已经这样做了一千次,但从未经历过如此奇怪的事情。也许这种行为仅在 iOS 8 中存在?

在我非常简单的 Prototype 单元格上,我有两个带有标签 102 和 103 的标签。但是当我想为它们设置文本时,它们总是 nil。

我仔细检查了标识符是否正确,并且该标签与 Storyboard 中的标签相同。

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString * identifier = @"secondReusableIdentifier";
    UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
    if (cell == nil){
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
    }

    for (UIView *subview in [cell subviews]) {
        NSLog(@"subview: %lu", subview.tag); // prints 0
    }

    UILabel * label1 = (UILabel *)[cell viewWithTag:102]; // returns nil
    UILabel * label2 = (UILabel *)[cell viewWithTag:103]; // returns nil
    if (self.items.count) {
        MyObject *obj = [self.items objectAtIndex:indexPath.row];
        label1.text = obj.someProperty;
        fuelPrice2.text = obj.someOtherProperty;
        }
    }
    return cell;

如有任何建议,我们将不胜感激。

如果

for (UIView *subview in [cell subviews]) {
    NSLog(@"subview: %lu", subview.tag); // prints 0
}

打印0,你为什么要这样做??

UILabel * label1 = (UILabel *)[cell viewWithTag:102];
UILabel * label2 = (UILabel *)[cell viewWithTag:103];

因此,如果您使用 IB 创建自定义单元格,则必须创建自定义 class 并使用它而不是简单的 UITableViewCell

在您的代码中,您正在创建一个新单元格,它与 Storyboard 中的不同。

更改此设置:这是旧方法,或者当单元格通过代码或笔尖而不使用情节提要时使用的方法。这段代码的意思是。

      NSString * identifier = @"secondReusableIdentifier";
// If I have available a cell with this identifier: secondReusableIdentifier, let's go to use it.
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil){
 // If not, we create a new cell with this identifier. This methods is previous to storyboard, and this methods create a new cell, but does´t look in Storyboard if this identifier exist, or something like that.

    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}

为此,另一方面,当 Apple 推出故事板时,框架会随着这种方法而增长,其工作方式如下:如果有一个可用的单元格,则使用它,如果没有,它会在故事板中查找具有此标识符的单元格,并且使用此信息创建一个新单元格。 (您也可以通过代码和 nib 文件使用此方法,但您必须在...之前注册 class)。

 // Be sure than: "secondReusableIdentifier", it's its identifier in storyboard
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"secondReusableIdentifier" forIndexPath:indexPath];

替换这个:

NSString * identifier = @"secondReusableIdentifier";
UITableViewCell *cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil){
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
}

通过

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"secondReusableIdentifier" forIndexPath:indexPath];

for creating a cell will solve your problem because, it always returns a cell. It either re uses existing cells or creates a new one and returns if there are no cells.

最重要的区别是 forIndexPath: 如果您没有为标识符注册 class 或 nib,版本会崩溃。在这种情况下,旧的(非 forIndexPath:) 版本 returns nil。

您必须注册一个 class 或 nib 才能使用它。但是,如果您在情节提要中创建 table 视图和单元格原型,情节提要加载器会负责注册您在情节提要中定义的单元格原型。

希望这对您有所帮助..:)