UITableView如何在reloadData上创建UITableViewCell的问题

时间:2011-03-27 22:24:47

标签: iphone objective-c uitableview

我知道有类似的问题,但批准的答案对我来说似乎并不适用。所以,我的情况是我有一个UITableView,我想通过扫描条形码来添加和删除项目。一切正常,但我无法让UITableView显示更新的信息。问题特别来自于tableView:cellForRowAtIndexPath:方法在初始化之后的每次其他重新加载。更具体地说,单元格总是 nil,因此它会跳过新的单元格创建逻辑。

对于像我这样的其他问题,答案是细胞标识符是问题所在。好吧,我试着弄乱它并且它没有用。这是我的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = nil;

    if (indexPath.section < vehicle.inventoryCategoriesCount) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"ModelCell"];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"ModelCell"] autorelease];

            NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"category == %@", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:@"@distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];

            cell.textLabel.text = model;
            cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"model == %@", model]] count]];
            cell.selectionStyle = UITableViewCellSelectionStyleNone;
        }
    } else {
        cell = [tableView dequeueReusableCellWithIdentifier:@"RemoveCell"];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"RemoveCell"] autorelease];

            cell.textLabel.text = @"Remove an Item";
            cell.textLabel.textColor = [UIColor redColor];
            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
        }
    }

    return cell;
}

因此,在此示例代码中,我有两个不同的单元格标识符用于单独的部分。它们是 ModelCell RemoveCell 。好吧,它们不能作为解决方案,因为没有任何反应。如果我在分配新单元时更改单元标识符,它可以工作,因为它只是擦除所有内容,因为标识符不匹配,但我会认为这是错误的,并且应该有一个更好的解决方案问题或者我只是没做正确的事。

我很感激对此有所帮助。到目前为止,我已经在这段代码上花了一天时间,而且我还没有到达任何地方,我想修复它并转到我的应用程序的其他部分......

提前感谢您的帮助!

更新

感谢@fluchtpunkt,问题已得到解决。对于其他可能在将来遇到此问题的人,这里是更正后的代码。我决定通过在其中添加章节号来使标识符更加独特。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = nil;

    if (indexPath.section < vehicle.inventoryCategoriesCount) {
        NSString *identifier = [NSString stringWithFormat:@"ModelCell-%d", indexPath.section];

        cell = [tableView dequeueReusableCellWithIdentifier:identifier];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier] autorelease];

            cell.selectionStyle = UITableViewCellSelectionStyleNone;
        }

        NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"category == %@", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:@"@distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];

        cell.textLabel.text = model;
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"model == %@", model]] count]];
    } else {
        cell = [tableView dequeueReusableCellWithIdentifier:@"RemoveCell"];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"RemoveCell"] autorelease];

            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
            cell.textLabel.textColor = [UIColor redColor];
        }

        cell.textLabel.text = @"Remove an Item";
    }

    return cell;
}

更新

最终的代码版本纠正了我对标识符如何工作的误解。我想我会保持简单,所以我在单元格样式类型之后命名了标识符。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = nil;

    if (indexPath.section < vehicle.inventoryCategoriesCount) {
        cell = [tableView dequeueReusableCellWithIdentifier:@"Value1"];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"Value1"] autorelease];

            cell.selectionStyle = UITableViewCellSelectionStyleNone;
        }

        NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"category == %@", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:@"@distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];

        cell.textLabel.text = model;
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"model == %@", model]] count]];
    } else {
        cell = [tableView dequeueReusableCellWithIdentifier:@"Default"];

        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Default"] autorelease];

            cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
            cell.textLabel.textColor = [UIColor redColor];
        }

        cell.textLabel.text = @"Remove an Item";
    }

    return cell;
}

3 个答案:

答案 0 :(得分:3)

将您的单元格配置置于if (cell == nil) { ... }之外if条件仅在没有单元格可以重用时才为真。你肯定想重用你的细胞。所以当你有一个有效的单元格时配置它们。

像这样:

if (indexPath.section < vehicle.inventoryCategoriesCount) {
    cell = [tableView dequeueReusableCellWithIdentifier:@"ModelCell"];

    if (cell == nil) {
        // only create a new cell if a dequeue was not successful.
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"ModelCell"] autorelease];
    }
    // whatever happened before you have a valid cell here.

    // configure cell:
    NSString *model = [[[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"category == %@", [vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:@"@distinctUnionOfObjects.model"] objectAtIndex:indexPath.row];

    cell.textLabel.text = model;
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"model == %@", model]] count]];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
} 

如果要优化代码,可以移动(cell == nil)条件内每个单元格相同的选项。例如,设置selectionStyle或更改textcolor

答案 1 :(得分:0)

Alex - 如果我在顶部查看您的代码,您就是这样做的:

cell = [tableView dequeueReusableCellWithIdentifier:@"ModelCell"];

但是,所有示例(和我的代码)都需要CellIdentifier的静态NSString

static NSString *MyIdentifier = @"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];

然后以预期的方式工作。

答案 2 :(得分:0)

你肯定会重复使用你的细胞。如果你把你的配置放在if(cell == nil)里面,它就可以在没有重复使用单元格的情况下工作。所以请将以下代码片段放在if(cell == nil)condition ------------

之外

if(cell == nil) {``   // 在此处输入代码 } NSString * model = [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@“category ==%@”,[vehicle.inventoryCategories objectAtIndex:indexPath.section]]] valueForKeyPath:@“@ distinctUnionOfObjects.model”] objectAtIndex:indexPath .row];

        cell.textLabel.text = model;
        cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", [[vehicle.inventory filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"model == %@", model]] count]];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;