滚动下来后,tableviews单元格正在改变

我正在一个分组tableview内的表单。 在这个表单中我有UI开关和文本框。 但是在向下滚动之后,单元格样式正在改变。

这是我的cellForRowAtIndex

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = nil; static NSString *MyIdentifier = @"GenericCell"; cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ; } NSString *text = nil; if(indexPath.section == CREDENTIALS_SECTION){ if (indexPath.row == 0) { NSLog(@"tot hier login"); UITextField *login = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)]; login.adjustsFontSizeToFitWidth = YES; login.placeholder = @"example@gmail.com"; login.keyboardType = UIKeyboardTypeEmailAddress; login.returnKeyType = UIReturnKeyNext; login.backgroundColor = [UIColor clearColor]; login.tag = 0; login.delegate = self; [login setEnabled: YES]; [cell addSubview:login]; }else if (indexPath.row == 1){ NSLog(@"tot hier pass"); UITextField *pass = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)]; pass.adjustsFontSizeToFitWidth = YES; pass.placeholder = @"Required"; pass.keyboardType = UIKeyboardTypeDefault; pass.returnKeyType = UIReturnKeyDone; pass.secureTextEntry = YES; pass.backgroundColor = [UIColor clearColor]; pass.tag = 0; pass.delegate = self; [cell addSubview:pass]; } if (indexPath.row == 0) { // Email text = @"Email"; } else if(indexPath.row == 1) { text = @"Password"; } }else if(indexPath.section == METHODS_SECTION){ UISwitch *toggleSwitch = [[UISwitch alloc]initWithFrame:CGRectMake(220, 10, 100, 30)]; toggleSwitch.tag = indexPath.row; [toggleSwitch addTarget:self action:@selector(toggleSwitched:) forControlEvents:UIControlEventValueChanged]; [cell addSubview:toggleSwitch]; if (indexPath.row == 0) { // Web text = @"Web applicatie"; } else if(indexPath.row == 1) { //Mobile text = @"Mobiele applicatie"; } else if(indexPath.row == 2) { //Mail text = @"E-mail"; } }else if(indexPath.section == PHONE_SECTION){ UITextField *phoneText = [[UITextField alloc] initWithFrame:CGRectMake(20, 10, 185, 30)]; phoneText.adjustsFontSizeToFitWidth = YES; phoneText.font = [UIFont fontWithName:@"Arial-BoldMT" size:18]; phoneText.keyboardType = UIKeyboardTypeNumberPad; phoneText.delegate = self; phoneText.textColor = [UIColor blackColor]; phoneText.text = _person.phone; [cell addSubview:phoneText]; }else if(indexPath.section == REMARK_SECTION){ UITextView *textView = [[UITextView alloc]initWithFrame:CGRectMake(20, 10, 280, 260)]; textView.text = _person.remark; textView.delegate = self; textView.font = [UIFont fontWithName:@"Arial" size:15.0]; textView.backgroundColor = [UIColor clearColor]; [cell addSubview:textView]; text = @""; }else if(indexPath.section == BUTTON_SECTION){ cell.backgroundColor = [UIColor redColor]; text = @"test"; } cell.textLabel.text = text; return cell; } 

经过一番search,我发现更多的人有这个问题。 而这个问题就在于这段代码。

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

但是我没有find解决办法。 希望有人能帮助!

亲切的问候!

澄清

好,所以在这里你看到我的表单截图。 下面我有一个红色的单元格(保存button),当我向下滚动其他单元格获得红色背景。 而一些单元格,文本属性正在改变。 在这里输入图像说明

那是不行的。 另外你还没有完全理解重用机制的工作原理。

你是做什么? 首先你要取一个细胞重新使用。 如果你到目前为止只有一个,那么问题就来了。 如果你没有得到一个,那么你创build一个新的。

当你创build一个新的,在用户开始滚动之前就是这样的情况下,你可以添加一些UIItems,这取决于部分和行。 我会解释为什么这不是一个聪明的事情。

然后用户滚动。 细胞将从屏幕上消失,然后可用于重新使用。 然后你将获取细胞重新使用。 但是很可能会发生这样的情况:那些单元格上已经有了额外的UI项目,因为您之前已经使用了它们。 在下面的过程中,您将添加新的UI项目,而不pipe在该单元格上是否已有其他UI项目。

你能做什么:

  1. 创build您自己的自定义表格单元格子类。 您可能需要的每个附加UI项目的一个子类。 这可能是最好的做法。 对于每个子类使用不同的重用标识符(!!!)这就是我会推荐! 不过,还有其他select:

  2. 你仍然可以和你的概念一起生活,但是为每种types的单元格创build一个单独的重用标识符types,并在其上添加一些额外的UI项目。 如果是这样,那么请确保这些UI项目仅在您的代码的if (cell == nil)分支中创build并添加为子视图。 只创build一次,然后重新使用它们。 信元重用 – ID可以是“email-display”,“email-input”,“password-display”,“password-input”,“switch”,…

  3. 上面解决scheme的一个方差是将行和段计算到重用标识符中。 如第0节和第2节的“cell-id-0.2” – 左右。 但是,您仍然必须确保您真的重新使用其他用户界面视图,并且不要在单元格填充数据时重新创build它们。 另外,第一部分的布局取决于您是要input密码和电子邮件还是只显示它们。 你仍然需要处理这些变化。

  4. 如果cell == nil(意思是如果一个单元格被重新使用),那么首先将其从您以前可能添加的每个UI项目中清除。 你可以通过标记你的UIViews来做到这一点 – 让我们说99 – (不同于0应该做的任何事情)创build时,当重复枚举所有子视图,并删除那些具有标签99.尽pipe你可以坚持代码你已经做了。

最简单的修复方法是:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GenericCell"] ; //some more code return cell; } 

这将从桌面视图中删除可重用性,但由于这是一个有限的设置视图,所以可以。 我仍然会build议从Hermann Klecker的解决scheme中拿1或2。

如果你还需要坚持UIControl状态然后使用

 static NSString *MyIdentifier = [NSString stringWithFormat:@"GenericCell%d",indexPath.row]; 

它将始终返回您的唯一表格行,您可以根据需要使用它。

尝试从单元中删除所有子视图,然后再使用它。 试试代码:

 if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] ; } else { [cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; } 

在单元格上添加子视图之前删除所有子视图。

 if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SimpleTableIdentifier]autorelease]; } else { //To remove the subview of cell. for (UIView *vwSubviews in [cell.contentView subviews]) { [vwSubviews removeFromSuperview]; } } 

它可以解决你的问题。

其实你这里有一些不好的代码。

在方法

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

除非它不在if (cell == nil) ,否则你不应该初始化和使用任何东西

 -(void)addSubview:(UIView*)view 

为什么?

单元格是从tableview中重用的视图。 所以如果你添加一些子视图,下次再使用这个单元格的时候,会添加更多的子视图。 只是它们重叠,可能导致内存泄漏。

不要忘记单元格是可重用的。 所以;

如果我有下面的代码,除非我不在其他地方设置文本。 预计所有的单元格在文本标签中都有文本“这是一个文本”。 因为它们是可重用的。

 if (someChangingBool) { cell.textLabel.text = @"this is a text"; } 

所以我需要有其他的东西,如果其中设置文本别的东西。

欲了解更多信息 。