繁体   English   中英

向下滚动后,tableviews单元格正在更改

[英]tableviews cells are changing after scrolling down

我正在分组表格视图中创建一个窗体。 在这种形式下,我有UIswitches和文本字段。 但是向下滚动后,单元格样式正在改变。

这是我的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;
}

经过一番搜索,我发现更多的人遇到了这个问题。 问题出在这段代码中。

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

但是我没有找到解决方案。 希望任何人都能帮忙!

亲切的问候!

澄清度

好的,在这里您可以看到我的表单的屏幕截图。 当我向下滚动时,我有一个红色的单元格(“保存”按钮),其他单元格正变成红色背景。 还有一些单元格,文本属性正在改变。 在此处输入图片说明

那不是功夫。 显然,您尚未完全了解重用机制的工作原理。

你是做什么? 首先,您获取要重用的单元格。 如果到目前为止,您获得-fine的结果,但问题稍后出现。 如果没有得到,则创建一个新的。

创建新的对象(在用户开始滚动之前即开始的情况下),然后根据部分和行添加一些UIItem。 我将解释为什么这实际上不是一件明智的事情。

然后用户滚动。 单元将从屏幕上消失,然后可供重复使用。 然后,您将获取单元以供重复使用。 但是很可能这些单元格上已经有其他UI项,因为您以前已经以这种方式使用它们。 在下面的过程中,您将添加新的UI项,无论该单元格上是否已经有其他UI-Item。

你能做什么:

  1. 创建您自己的定制表单元格子类。 每个子集可能需要一个子类。 那可能是最整洁的方式。 对于每个子类,请使用不同的重用标识符(!!!),这是我的建议! 但是,还有其他选择:

  2. 您仍然可以接受您的概念,但是可以为每种类型的单元格创建一种单独类型的重用标识符,其中包含某种类型的其他ui项。 如果是这样,请确保仅在代码的if (cell == nil)分支中创建和添加这些UI项作为子视图。 仅创建一次,然后重新使用它们。 单元重用ID可以是“电子邮件显示”,“电子邮件输入”,“密码显示”,“密码输入”,“开关”,...

  3. 上面解决方案的一个变化是,计算重用标识符中的行和节。 例如第0节和第2行的“ cell-id-0.2”-左右。 但是,仍然需要确保您确实重用了其他UI视图,并且每次在单元格填充数据时都不要重新创建它们。 另外,第一部分中的布局取决于您是输入密码还是电子邮件还是仅显示它们。 您仍然必须应对这些变化。

  4. 如果cell == nil-表示是否已重复使用某个单元格-那么请先清除之前可能添加的每个UI项中的单元格。 您可以通过在创建时以及在所有子视图上重用枚举并删除带有标签99的子视图时,使用-假设99-(任何与0不同的方法)来标记UIViews来做到这一点。尽管如此,您仍然可以坚持使用你已经做了。

最简单的解决方法是:

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

这会从表视图中删除可重用性,但是由于它是有限的设置视图,因此可以。 我仍然建议从Hermann Klecker的解决方案中选择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"; 
}

因此,如果需要将文本设置为其他内容,则需要使用其他方法。

有关更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM