1

下面显示的 tableView 包含label. 它们被添加subView为每个单元格。

当我第一次运行我的程序时,屏幕上出现的单元格具有正确的文本。但是当我滚动表格时,标签中的文本开始混淆。据我了解,创建单元格时,一个单元格的标签会覆盖在另一个单元格的顶部。这已在后两个屏幕截图中显示。每次滚动后,不同的单元格会重叠在一起。(所以没有固定的模式。)我试图通过观察哪个单元格从屏幕上出来以及哪个单元格正在进入来理解这个问题。我试图将此信息与单元格上的标签相关联,但我无法理解。

我请求您帮助我了解造成这种差异的原因。

谢谢!

在此处输入图像描述

我的代码的相关部分如下:

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

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

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    NSLog(@"s = %d, r = %d", indexPath.section, indexPath.row);

    if (indexPath.section == 0)
    {
        switch(indexPath.row)
        {
            case 0:
            [cell addSubview:classA];
            break;

            case 1:
            [cell addSubview:classB];
            break;

        case 2:
            [cell addSubview:classC];
            break;

        case 3:
            [cell addSubview:classD];
            break;

        case 4:
            [cell addSubview:classE];
            break;

        default:
            break;
    }
}

if(indexPath.section == 1)
{
    switch(indexPath.row)
    {
        case 0:
            [cell addSubview:classF];
            break;

        case 1:
            [cell addSubview:classG];
            break;

        case 2:
            [cell addSubview:classH];
            break;

        default:
            break;
    }
}

if(indexPath.section == 2)
{
    switch (indexPath.row)
    {
        case 0:
            [cell addSubview:classI];
            break;

        case 1:
            [cell addSubview:classJ];
            break;

        case 2:
            [cell addSubview:classK];
            break;

        default:
            break;
    }
}

return cell;
}
4

3 回答 3

3

重复使用表格视图单元格:如果向上或向下滚动,dequeueReusableCellWithIdentifier可能会返回一个以前用于不同(现在不可见)行的单元格。

在这种情况下,单元格已经包含您的一个子视图,并且您添加了一个额外的子视图。

于 2012-11-19T19:32:56.583 回答
1

原因是,您正在使用dequeueReusableCellWithIdentifier重复使用单元格。因此,当您滚动时,超出可见区域的单元格将被重新用于当前可见单元格。

由于您已经classB在这些单元格中添加了诸如 etc.. 之类的标签并且之后没有删除,之后当您classI在相同的重复使用的单元格中添加诸如 etc.. 之类的标签时,它会被绘制在此标签的顶部。由于这些标签的背景颜色设置为透明色,因此它也会显示在其后面绘制的标签,从而给人一种重叠的感觉。

根据屏幕截图,所有单元格看起来都相同,您绝对可以使用dequeueReusableCellWithIdentifier. 那么,为什么不改变在外部创建标签的逻辑,cellForRowAtIndexPath而只是cell.TextLabel.text = @"Class B";在此方法内的相应 if 条件中将其用作 etc..?

你的代码看起来像,

if (indexPath.section == 0)
    {
        switch(indexPath.row)
        {
            case 0:
            cell.textLabel = [self createLabelForRow:indexPath.row section:indexPath.section];
//or if it is jut a simple label, you can just set font and other properties in cell.textLabel directly
            cell.textLabel.text = @"Class A";
            break;

更新:dequeueReusableCellWithIdentifier如果所有单元格都是静态的,这是一个不太好的重用修复。但这不是推荐的方法。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

  NSString *CellIdentifier = [NSString stringWithFormat:@"CellForRow%dSection%d",indexPath.row, indexPath.section];
  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
  if (cell == nil)
   { 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
   }

  //or try this

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

Update2:因此,如果您遇到上述问题,请尝试此操作。使用我的第一种方法并执行以下操作。

if (indexPath.section == 0)
    {
        switch(indexPath.row)
        {
            case 0:
            cell.textLabel = [self createLabelForRow:indexPath.row section:indexPath.section];

            // or do the following,

            [self removeAllTextFieldsFromCell:cell];
            UITextField *aTextField = [self createTextFieldForRow:indexPath.row section:indexPath.section];
            [cell.contentView addSubview:aTextField];
         }

removeAllTextFieldsFromCell:方法上使用 RA 的建议。

例如:-

- (void)removeAllTextFieldsFromCell:(UITableViewCell *)cell {

    for (UITextField *textField in cell.contentViews.subViews) {
        [textField removeFromSuperView];
    }
}

或者只是使用,

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

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

    cell.selectionStyle = UITableViewCellSelectionStyleNone;

    NSLog(@"s = %d, r = %d", indexPath.section, indexPath.row);

    //if it is all textfields in the cell, it will look like,
    [self removeAllTextFieldsFromCell:cell];
    UITextField *aTextField = [self createTextFieldForRow:indexPath.row section:indexPath.section];
    [cell.contentView addSubview:aTextField];

    return cell;
}
于 2012-11-19T19:33:27.107 回答
1

正如您在评论中所说textfield,那么您需要remove the old textField从您的单元格中。您可以在if statement for indexPath.section checking.

for (UITextField *textField in cell.contentViews.subViews) {
    [textField removeFromSuperView];
}
于 2012-11-19T19:43:40.863 回答