【问题标题】:What is wrong with my UITableView cellForRowAtIndex for Single Selection?我的 UITableView cellForRowAt 单选索引有什么问题?
【发布时间】:2023-03-04 19:17:01
【问题描述】:

下面是UITableView 的代码,但是当我滚动它时它的行为很奇怪(太烦人了)......这个问题是由于reuseIdentifier......但不知道如何解决......

- (UITableViewCell *)tableView:(UITableView *)tableView1 cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView1 dequeueReusableCellWithIdentifier:CellIdentifier];

    NSInteger imgTag = 1;
    NSInteger lblTag = 2;

    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;

        UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(2, 2, 52, 52)];
//        Image:[UIImage imageNamed:[self.glassType objectAtIndex:indexPath.row]]];
        imgView.tag = imgTag;
        [cell.contentView addSubview:imgView];
        [imgView release];

        UILabel *lblName = [[UILabel alloc] initWithFrame:CGRectMake(60, cell.frame.size.height/4, 200, 21)];
//        lblName.text = [self.glassName objectAtIndex:indexPath.row];
        lblName.tag = lblTag;
        [cell addSubview:lblName];
        [lblName release];
    }

    NSInteger imgIndex = 2;
    NSInteger lblIndex = 3;

    ((UIImageView *)[cell viewWithTag:imgTag]).image = [[self.glassType objectAtIndex:indexPath.row] objectAtIndex:imgIndex];
    ((UILabel *)[cell viewWithTag:lblTag]).text = [[self.glassName objectAtIndex:indexPath.row] objectAtIndex:lblIndex];

    return cell;
}

- (void)tableView:(UITableView *)tableView1 didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView1 cellForRowAtIndexPath:indexPath];
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}

如何为索引处的行制作单元格,以便即使滚动也保持不变???还有如何在UITableView中进行单选??

【问题讨论】:

  • 你应该使用标签 100 及以上

标签: iphone objective-c ios uitableview


【解决方案1】:

答案是您不应该在“if (cell == nil) { ...”子句之外将子视图添加到表格单元格,否则它们会在重新添加到同一个单元格时一遍又一遍地添加到用过。

查看我对这个问题的回答以获得更详细的解释,包括如何修复它的代码:

cellForRowAtIndexPath memory management

您也不能将状态存储在表格单元格中,因为一旦它们滚动到屏幕外,它们就会被回收并重新出现在表格中的不同索引处。您需要设置一个模型对象数组来存储表格单元格的状态(例如它们的附件类型应该是什么)。更详细的解释可以在我对这个问题的回答中找到:

Looping through UITableViewCells of a UITableView

如果您修复了如何将子视图添加到单元格,并将“勾选”状态存储在模型对象数组中并设置 cell.accessoryType(以便在单元格出队时可以恢复),那么你的行选择方法是正确的。

所以把它放在你的 tableView:cellForRowAtIndexPath: 方法中,就在 return cell; 之前:

MyModelObject *object = [self.arrayOfModelObjects objectAtIndex:indexPath.row];
BOOL isChecked = object.checked;
cell.accessoryType = isChecked? UITableViewCellAccessoryCheckmark: UITableViewCellAccessoryNone;

并且在您的tableView: didSelectRowAtIndexPath: 方法中,摆脱当前的逻辑并替换为:

- (void)tableView:(UITableView *)tableView1 didSelectRowAtIndexPath:(NSIndexPath *)indexPath
    for (int i = 0; i < [self.arrayOfModelObjects count]; i++)
    {
        MyModelObject *object = [self.arrayOfModelObjects objectAtIndex:i];
        object.checked = (i == indexPath.row); // only check the one we just tapped
    }

    //refresh table to update the accessory views for all rows
    [tableView1 reloadData];
}

显然将arrayOfModelObjects 替换为您自己的模型实现。如果您不想为此创建自定义类,则可以只使用包含布尔值的 NSNumber 对象数组。

【讨论】:

  • 请查看我更新的代码。它的行为仍然很奇怪...我的图像在滚动时随机移动。我已将代码保存在 if 块中,但问题仍然存在...
  • @DShah 您在第一个链接中阅读了尼克的回答吗?阅读他的答案,并遵循该代码中的模型。 提示查看标签的使用以及if(cell == nil){}的结束位置。
  • 将您的问题更新为现在可以工作的代码有点令人困惑,而无需包含注释来解释您已经这样做了。另外,如果我解决了你的问题,你能接受答案吗?那样我会得到更多的分数:-)
  • 嘿,现在我遇到了与 cell.accessoryType 相同的问题...当我滚动时,我选择了一些单元格。我想要的是一次只应该选择一个单元格。对于上面的代码,我可以处理对象,但是对于附件类型怎么办??
  • 将每一行的检查状态存储在一个数组中。如果您尚未使用自定义对象数组作为数据源,则可以使用包含布尔值的 NSNumber 对象数组。当您点击一个单元格时,将数组中的正确布尔值设置为 true,并将所有其他布尔值清除为 false。然后使用 [tableView reloadData] 重新加载表格。根据数组中的布尔值在 cellForRowAtIndexPath 方法中设置附件类型。
【解决方案2】:

回收队列就像一个池,之前创建的 Cell 被存储在其中,然后才能重用它们。例如,当您向上滚动时,当单元格在上方消失时,它会存储在队列中,并可供将出现在底部的单元格使用。好吗?

实际上真正创建的单元格的数量正是您可以在表格中显示的最大同时单元格(大多数情况下为 3 到 8 个)。换句话说,您的 if (cell == nil) 代码在第一次 reloadData 时执行(或多或少 3 到 8 次),以创建您的表格所需的单元格池。

然后,您在单元格上所做的所有内容都会保持原样,并在您将其出列时再次出现。现在很容易理解,在您的代码中,您必须在 if (cell == nil) 块之外进行所有严格的行相关设置。同样的方法,不要在if (cell == nil)块之外添加子视图,您可以想象每次重置出列单元格时会添加数千个子视图!

提示:如果您需要在重用单元格之前进行一些自定义清理(例如将图像设置为空白),您可以创建自定义UITableviewCell 类并实现prepareForReuse 方法。

清楚了吗?

【讨论】:

    【解决方案3】:

    始终在 viewWillAppear 方法而不是 viewDidLoad 中重新加载您的 tableView。

    • (void) viewWillAppear:(BOOL)动画{

      [self.tableView reloadData];

      }

    这可以避免大多数意外和烦人的问题。 :)

    【讨论】:

      猜你喜欢
      • 2020-03-04
      • 1970-01-01
      • 1970-01-01
      • 2020-08-06
      • 2017-12-05
      • 1970-01-01
      • 2016-03-15
      • 1970-01-01
      • 2019-07-29
      相关资源
      最近更新 更多