标签文字越来越混乱

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

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

我请你帮助我理解这种差异的原因。

谢谢!

在这里输入图像说明

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

 - (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; } 

原因是,您正在使用dequeueReusableCellWithIdentifier重用单元格。 所以当你滚动的时候,可见区域外面的单元格会被重新用于当前的可见单元格。

既然你已经在这些单元格中添加了classI等标签,并且之后没有被删除,之后当你在相同的重用单元格中添加标签(如classI等)时,它将被绘制在这个标签之上。 由于这些标签的背景颜色设置为清晰的颜色,因此会显示在其后面的标签,从而产生重叠的感觉。

按照屏幕截图,所有的单元看起来都是一样的,你可以肯定地使用dequeueReusableCellWithIdentifier来重用单元。 那么为什么你不改变你在cellForRowAtIndexPath之外创build标签的逻辑,而是把它当作cell.TextLabel.text = @"Class B"; 在这个方法里面相应的条件里面呢?

你的代码看起来像,

 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的build议。

例如: –

 - (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; } 

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

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

正如你在评论中所说的textfield ,那么你需要从你的单元格中remove the old textField 。 你可以在你的if statement for indexPath.section checking之前添加这个代码if statement for indexPath.section checking

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