UITableViewCell 滚动时复制 UITextfield 子视图

Posted

技术标签:

【中文标题】UITableViewCell 滚动时复制 UITextfield 子视图【英文标题】:UITableViewCell duplicating UITextfield subviews when scrolling 【发布时间】:2014-08-21 14:16:34 【问题描述】:

我试图弄清楚为什么我的SubviewsUITableview 滚动时会重复。如果我在IF statement 中添加Subviews 以重复使用单元格,它将复制并重新排序Subviews。如果我把代码放在外面,滚动时把Subviews 放在另一个上面会搞砸。下面是我的代码。我做错了什么导致这个?

static NSString *cellIdentifier = @"Cell";

UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:cellIdentifier];

if (cell == nil) 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];





cell.accessoryType = UITableViewCellAccessoryNone;

    UIColor *cellBackgroundColor = [rgbConverter convertColor:@"#202e35"];
    cell.backgroundColor = cellBackgroundColor;
    // cell.contentView.backgroundColor    = color;


    if ((indexPath.row == 0) && (indexPath.section == 0)) 
        fullName = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 200, 25)];
        fullName.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        fullName.autocorrectionType = UITextAutocorrectionTypeNo;
        [fullName setClearButtonMode:UITextFieldViewModeWhileEditing];
        fullName.textColor  = [UIColor lightGrayColor];
        [fullName setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        fullName.returnKeyType = UIReturnKeyNext;
        fullName.background = [UIImage imageNamed:@"textfieldBG.png"];
        [fullName setTag:1];
        [fullName setText:@""];

        [cell.contentView  addSubview:fullName];

    
    if ((indexPath.row == 1)  && (indexPath.section == 0))
        accountNumber = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 200, 25)];
        accountNumber.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        //accountNumber.placeholder = @"MLGW Account Number";
        accountNumber.autocorrectionType = UITextAutocorrectionTypeNo;
        [accountNumber setClearButtonMode:UITextFieldViewModeWhileEditing];
        accountNumber.keyboardType = UIKeyboardTypeNumberPad;
        accountNumber.returnKeyType = UIReturnKeyNext;
        accountNumber.textColor  = [UIColor lightGrayColor];
        [accountNumber setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [accountNumber setTag:2];
        [accountNumber setText:@""];
        accountNumber.background = [UIImage imageNamed:@"textfieldBG.png"];

        [cell.contentView  addSubview:accountNumber];

    
    if ((indexPath.row == 2)  && (indexPath.section == 0))
        address = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 200, 25)];
        address.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        address.placeholder = @"Address";
        address.autocorrectionType = UITextAutocorrectionTypeNo;
        [address setClearButtonMode:UITextFieldViewModeWhileEditing];
        address.keyboardType = UIKeyboardTypeDefault;
        address.returnKeyType = UIReturnKeyNext;
        address.textColor  = [UIColor lightGrayColor];
        [address setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [address setTag:3];
        [address setText:@""];
        address.background = [UIImage imageNamed:@"textfieldBG.png"];
        [cell.contentView  addSubview:address];

    
    if ((indexPath.row == 3)  && (indexPath.section == 0))
        aptNumber = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 200, 25)];
        aptNumber.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        aptNumber.placeholder = @"Apartment Number";
        aptNumber.autocorrectionType = UITextAutocorrectionTypeNo;
        aptNumber.returnKeyType = UIReturnKeyNext;
        [aptNumber setClearButtonMode:UITextFieldViewModeWhileEditing];
        aptNumber.keyboardType = UIKeyboardTypeNamePhonePad;
        aptNumber.textColor  = [UIColor lightGrayColor];
        [aptNumber setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [aptNumber setTag:4];
        [aptNumber setText:@""];
        aptNumber.background = [UIImage imageNamed:@"textfieldBG.png"];
        [cell.contentView  addSubview:aptNumber];

    
    if ((indexPath.row == 4)  && (indexPath.section == 0))
        city = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 180, 25)];
        city.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        city.placeholder = @"City";
        city.autocorrectionType = UITextAutocorrectionTypeNo;
        city.returnKeyType = UIReturnKeyNext;
        [city setClearButtonMode:UITextFieldViewModeWhileEditing];
        city.keyboardType = UIKeyboardTypeDefault;
        city.textColor  = [UIColor lightGrayColor];
        [city setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [city setTag:5];
        [city setText:@""];
        city.background = [UIImage imageNamed:@"textfieldBG.png"];
        [cell.contentView  addSubview:city];

        zip = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+210, cell.frame.origin.y+10,80, 25)];
        zip.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        zip.placeholder = @"Zip";
        zip.autocorrectionType = UITextAutocorrectionTypeNo;
        zip.returnKeyType = UIReturnKeyNext;
        [zip setClearButtonMode:UITextFieldViewModeWhileEditing];
        zip.keyboardType = UIKeyboardTypeNumberPad;
        zip.textColor  = [UIColor lightGrayColor];
        [zip setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [zip setTag:6];
        [zip setText:@""];
        zip.background = [UIImage imageNamed:@"textfieldBG.png"];
        [cell.contentView  addSubview:zip];

    
     if ((indexPath.row == 5)  && (indexPath.section == 0))
        phoneNbr = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 200, 25)];
        phoneNbr.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        phoneNbr.placeholder = @"Phone Number";
        phoneNbr.autocorrectionType = UITextAutocorrectionTypeNo;
        phoneNbr.returnKeyType = UIReturnKeyNext;
        [phoneNbr setClearButtonMode:UITextFieldViewModeWhileEditing];
        phoneNbr.keyboardType = UIKeyboardTypeNumberPad;
        phoneNbr.textColor  = [UIColor lightGrayColor];
        [phoneNbr setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [phoneNbr setTag:7];
        [phoneNbr setText:@""];
        phoneNbr.background = [UIImage imageNamed:@"textfieldBG.png"];
        [cell.contentView  addSubview:phoneNbr];

    
    if ((indexPath.row == 6)  && (indexPath.section == 0))
        emailAddress = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 200, 25)];
        emailAddress.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        emailAddress.placeholder = @"Email Address";
        emailAddress.returnKeyType = UIReturnKeyNext;
        emailAddress.autocorrectionType = UITextAutocorrectionTypeNo;
        [emailAddress setClearButtonMode:UITextFieldViewModeWhileEditing];
        emailAddress.keyboardType = UIKeyboardTypeEmailAddress;
        emailAddress.textColor  = [UIColor lightGrayColor];
        [emailAddress setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [emailAddress setTag:8];
        [emailAddress setText:@""];
        emailAddress.background = [UIImage imageNamed:@"textfieldBG.png"];
        [cell.contentView  addSubview:emailAddress];

    
    if ((indexPath.row == 7)  && (indexPath.section == 0))
        validateEmail = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 200, 25)];
        validateEmail.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        validateEmail.placeholder = @"Re-enter Email Address";
        validateEmail.returnKeyType = UIReturnKeyNext;
        validateEmail.autocorrectionType = UITextAutocorrectionTypeNo;
        [validateEmail setClearButtonMode:UITextFieldViewModeWhileEditing];
        validateEmail.keyboardType = UIKeyboardTypeEmailAddress;
        validateEmail.textColor  = [UIColor lightGrayColor];
        [validateEmail setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [validateEmail setTag:9];
        [validateEmail setText:@""];
        validateEmail.background = [UIImage imageNamed:@"textfieldBG.png"];
        [cell.contentView  addSubview:validateEmail];

    
    if ((indexPath.row == 0)  && (indexPath.section == 1))
         oneTimeDonationBtn = [[UIButton alloc]initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 38, 32)];
        [oneTimeDonationBtn setImage:[UIImage imageNamed:@"radioBox.png"] forState:UIControlStateNormal];
        [oneTimeDonationBtn addTarget:self action:@selector(oneTimeAmountAction:) forControlEvents:UIControlEventTouchUpInside];
        oneTimeDonation = [[UITextField alloc] initWithFrame:CGRectMake(oneTimeDonationBtn.frame.origin.x+35, cell.frame.origin.y+13, 150, 25)];
        oneTimeDonation.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        oneTimeDonation.placeholder = @"One Time Donation";
        oneTimeDonation.autocorrectionType = UITextAutocorrectionTypeNo;
        oneTimeDonation.returnKeyType = UIReturnKeyNext;
        [oneTimeDonation setClearButtonMode:UITextFieldViewModeWhileEditing];
        oneTimeDonation.keyboardType = UIKeyboardTypeDecimalPad;
        oneTimeDonation.textColor  = [UIColor lightGrayColor];
        [oneTimeDonation setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [oneTimeDonation setTag:10];
        [oneTimeDonation setText:@""];
        oneTimeDonation.background = [UIImage imageNamed:@"textfieldBG.png"];
        [cell.contentView  addSubview:oneTimeDonationBtn];
        [cell.contentView  addSubview:oneTimeDonation];

    
    if ((indexPath.row == 0) && (indexPath.section == 2))
        oneDollarBtn = [[UIButton alloc]initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 38, 32)];
         [oneDollarBtn setImage:[UIImage imageNamed:@"radioBox.png"] forState:UIControlStateNormal];
        [oneDollarBtn addTarget:self action:@selector(oneDollarAction:) forControlEvents:UIControlEventTouchUpInside];
        [cell.contentView  addSubview:oneDollarBtn];

        oneDollarLbl = [[UILabel alloc ] initWithFrame:CGRectMake(oneDollarBtn.frame.origin.x+35, cell.frame.origin.y+10, 38, 32)];
        oneDollarLbl.text = @"$1";
        oneDollarLbl.textColor = [UIColor lightGrayColor];
        [cell.contentView  addSubview:oneDollarLbl];

        fiveDollarBtn = [[UIButton alloc]initWithFrame:CGRectMake(oneDollarLbl.frame.origin.x+35, cell.frame.origin.y+10, 38, 32)];
        [fiveDollarBtn setImage:[UIImage imageNamed:@"radioBox.png"] forState:UIControlStateNormal];
        [fiveDollarBtn addTarget:self action:@selector(fiveDollarAction:) forControlEvents:UIControlEventTouchUpInside];
        [cell.contentView  addSubview:fiveDollarBtn];

        fiveDollarLbl = [[UILabel alloc ] initWithFrame:CGRectMake(fiveDollarBtn.frame.origin.x+35, cell.frame.origin.y+10, 38, 32)];
        fiveDollarLbl.text = @"$5";
        fiveDollarLbl.textColor = [UIColor lightGrayColor];
        [cell.contentView  addSubview:fiveDollarLbl];

        tenDollarBtn = [[UIButton alloc]initWithFrame:CGRectMake(fiveDollarLbl.frame.origin.x+35, cell.frame.origin.y+10, 38, 32)];
        [tenDollarBtn setImage:[UIImage imageNamed:@"radioBox.png"] forState:UIControlStateNormal];
        [tenDollarBtn addTarget:self action:@selector(tenDollarAction:) forControlEvents:UIControlEventTouchUpInside];
        [cell.contentView  addSubview:tenDollarBtn];

        tenDollarLbl = [[UILabel alloc ] initWithFrame:CGRectMake(tenDollarBtn.frame.origin.x+35, cell.frame.origin.y+10, 38, 32)];
        tenDollarLbl.text = @"$10";
        tenDollarLbl.textColor = [UIColor lightGrayColor];
        [cell.contentView  addSubview:tenDollarLbl];
    

if ((indexPath.row == 1)  && (indexPath.section == 2))
    otherAmountBtn = [[UIButton alloc]initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 38, 32)];
    [otherAmountBtn setImage:[UIImage imageNamed:@"radioBox.png"] forState:UIControlStateNormal];
    [otherAmountBtn addTarget:self action:@selector(otherAmountAmountAction:) forControlEvents:UIControlEventTouchUpInside];
        otherAmount = [[UITextField alloc] initWithFrame:CGRectMake(otherAmountBtn.frame.origin.x+35, cell.frame.origin.y+13, 150, 25)];
        otherAmount.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        otherAmount.placeholder = @"Other Amount";
        otherAmount.autocorrectionType = UITextAutocorrectionTypeNo;
        otherAmount.returnKeyType = UIReturnKeyNext;
        [otherAmount setClearButtonMode:UITextFieldViewModeWhileEditing];
        otherAmount.keyboardType = UIKeyboardTypeDecimalPad;
        otherAmount.textColor  = [UIColor lightGrayColor];
        [otherAmount setValue:[UIColor lightGrayColor] forKeyPath:@"_placeholderLabel.textColor"];
        [otherAmount setTag:10];
        [otherAmount setText:@""];
        otherAmount.background = [UIImage imageNamed:@"textfieldBG.png"];
    [cell.contentView  addSubview:otherAmountBtn];
        [cell.contentView  addSubview:otherAmount];

    


    if ((indexPath.row == 0)  && (indexPath.section == 3))
        comments = [[UITextView alloc] initWithFrame:CGRectMake(cell.frame.origin.x+10, cell.frame.origin.y+10, 280, 100)];
        comments.font = [UIFont fontWithName:@"HelveticaNeue" size:15];
        comments.autocorrectionType = UITextAutocorrectionTypeNo;
        comments.keyboardType = UIKeyboardTypeDefault;
        comments.textColor  = [UIColor lightGrayColor];
        [comments setTag:11];
        [comments setText:@""];
        comments.contentInset = UIEdgeInsetsMake(2.0, 1.0, 0.0, 0.0);
        [cell.contentView  addSubview:comments];


    



//cell.imageView.image = [UIImage imageNamed:@"settings_icon.png"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.backgroundColor = [UIColor clearColor];

return cell;

【问题讨论】:

正如其他人所暗示的那样,如果您成功检索到“可重用”单元格,如果您已添加视图,则必须在继续之前对其进行“清理”。 您可以在添加新的子视图之前删除以前的子视图。如果 else 循环,把它放在你面前 【参考方案1】:

当您仅使用一个 cellIdentifier 通过调用 dequeueReusableCellWithIdentifier 方法重用不同类型的单元格时,就会发生这种情况。

在您的代码中,您在不同的 indexPath 添加不同的视图,但您不知道 dequeueReusableCellWithIdentifier 方法给出的单元格是什么。

例如,当您将address 视图添加到重复使用的单元格时,它可能已经有一个fullName 子视图。然后你会得到意想不到的结果。

解决问题的方法有很多。

这里有两个我觉得很适合你的情况,你可以选择任何你喜欢的:

    由于您的单元格内容不是那么“可重复使用”,如果性能没有问题,我建议您根本不要使用dequeueReusableCellWithIdentifier

    你最好为不同类型的单元格使用不同的cellIdentifier

【讨论】:

【参考方案2】:

主要原因是dequeueReusableCellWithIdentifier,顾名思义,无论顺序如何,都会获取一个已经创建的单元格。我猜它只缓存与可见单元格一样多的单元格。

当您向上滚动时,它会为您提供一个已创建(并已填充)的单元格。

用这个替换单元格的创建:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath]; 

同时删除 if (cell == nil)。同时删除其他单元格创建

请记住 dequeueReusableCellWithIdentifier:forIndexPath: 永远不会返回 nil。因此,最好检查单元格是否已填充以跳过子视图的创建。

【讨论】:

【参考方案3】:

你的代码有点难读。

每次你必须自定义单元格时,你不应该使用UITableViewCell,而是应该继承它,并在你的自定义类中自定义它。

根据我的经验,当涉及部分和行时,我发现 if 语句很复杂。

我建议你使用 switch 语句,你可以为每个案例提供逻辑。

这将使您的生活更轻松,大致如下:

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

    switch (indexPath.section) 
        case 0:
            switch (indexPath.row) 
                case 0:
                    //fullName custom cell
                    break;
                case 1:
                    //account number custom cell
                    break;

                default:
                    break;
            
            break;

        default:
            break;
    

    return cell;


【讨论】:

【参考方案4】:

首先将文本字段标签设置为某个常量,您可以使用单元格 indexPath 获取文本字段。其次添加文本字段,如果它还没有,如下所示;

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

     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

     //check if you already have textfield, say a constant tag is 100
     UITextField *myTextField ;

    if(cell)

            myTextField = (UITextField *)[cell.contentView viewWithTag:100];
    

    if (cell == nil) 
               cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];

    //now if myTextField is nil then only init it
    if(!myTextField)
           //Configure textfield here and add to cell content view
    


 

//now all things are configure for cell , assign whatever text you want to myTextField
if(indexPath.row == 0 && indexPath.section == 0)

  //.......
  [myTextField setText:@"XYZ"];






【讨论】:

以上是关于UITableViewCell 滚动时复制 UITextfield 子视图的主要内容,如果未能解决你的问题,请参考以下文章

键盘出现时如何滚动 UITableviewcell 向上滚动? [复制]

UITableViewCell 滚动时复制 UITextfield 子视图

当单元格滚动回视图时表格崩溃

未分配给父 UIViewController 视图属性时,UITableView 不滚动

VM:UITableViewLabel 占用内存 iOS

使用自定义 UITableViewCell 时,imageview 框架为零