在 UITableView 内时 UITextField 中的文本重复

Posted

技术标签:

【中文标题】在 UITableView 内时 UITextField 中的文本重复【英文标题】:Duplicates of text in UITextField when inside UITableView 【发布时间】:2013-03-16 13:33:45 【问题描述】:

我在UITableView 中创建了一个UITextField。我输入数据并关闭键盘。但是,当我向下滚动并隐藏 UITextField 然后再次向上滚动时,'UITextField' 数据被复制,如下所示:

视图的原始负载:

输入数据:

隐藏文本字段后再次开始编辑:

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

static NSString *CellIdentifier = @"Cell";

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) 
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                   reuseIdentifier:CellIdentifier];


if ([indexPath section] == 0)  // Email & Password Section
    cell.textLabel.text = @"Subject";
 else 
    cell.textLabel.text = @"Task";


cell.selectionStyle = UITableViewCellSelectionStyleNone;

if ([indexPath section] == 0) 
    UITextField *subject = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
    subject.adjustsFontSizeToFitWidth = YES;
    subject.textColor = [UIColor blackColor];
    if ([indexPath row] == 0) 
        subject.placeholder = @"Maths";
        subject.keyboardType = UIKeyboardTypeEmailAddress;
        subject.returnKeyType = UIReturnKeyNext;
    
    subject.backgroundColor = [UIColor clearColor];
    subject.autocorrectionType = UITextAutocorrectionTypeNo;
    subject.autocapitalizationType = UITextAutocapitalizationTypeWords;
    subject.tag = 0;
    subject.clearButtonMode = UITextFieldViewModeNever;
    [cell.contentView addSubview:subject];
 else 
    UITextView *task = [[UITextView alloc] initWithFrame:CGRectMake(102, 0, 185, 40)];
    task.text = @"fasfashfjasfhasfasdjhasgdgasdhjagshjdgashjdgahjsdghjasgasdashgdgjasd";
    task.editable = NO;
    task.scrollEnabled = NO;
    task.userInteractionEnabled = NO;
    task.textColor = [UIColor colorWithRed: 62.0/255.0 green: 85.0/255.0 blue:132.0/255.0 alpha:1.0];
    task.backgroundColor = [UIColor clearColor];




return cell;

【问题讨论】:

发布您的 textField 委托方法 【参考方案1】:

就像 Richard 所说,单元格被重复使用(这就是标识符的目的),这就是为什么您在 tableView:cellForRowAtIndexPath: 中测试由 dequeueReusableCellWithIdentifier: 返回的 nil 值。 如果一个单元格已经存在(即之前分配的)并且不再显示,dequeueReusableCellWithIdentifier: 将使用这个单元格来显示新出现的单元格的内容。

您所做的是在每次显示而不是创建单元格时添加您的UITextView。因此,每次将一个单元格滚动出屏幕并弹出一个新单元格时,您都会在单元格中附加一个新的UITextView。您应该只在方法的if (cell == nil) 部分添加子视图。由于您的单元格的内容非常不同,我建议使用两个不同的标识符。

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


    static NSString *CellIdentifierForSection0 = @"Cell0";
    static NSString *CellIdentifierForSection1 = @"Cell1";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: [indexPath section] == 0 ? CellIdentifierForSection0 : CellIdentifierForSection1];
    if (cell == nil) 

        if ([indexPath section] == 0)  // Email & Password Section

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:CellIdentifierForSection0];
            cell.textLabel.text = @"Subject";

            UITextField *subject = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 185, 30)];
            subject.adjustsFontSizeToFitWidth = YES;
            subject.textColor = [UIColor blackColor];
            if ([indexPath row] == 0) 
                subject.placeholder = @"Maths";
                subject.keyboardType = UIKeyboardTypeEmailAddress;
                subject.returnKeyType = UIReturnKeyNext;
            
            subject.backgroundColor = [UIColor clearColor];
            subject.autocorrectionType = UITextAutocorrectionTypeNo;
            subject.autocapitalizationType = UITextAutocapitalizationTypeWords;
            subject.tag = 0;
            subject.clearButtonMode = UITextFieldViewModeNever;
            [cell.contentView addSubview:subject];
         else 

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                       reuseIdentifier:CellIdentifierForSection1];
            cell.textLabel.text = @"Task";

            UITextView *task = [[UITextView alloc] initWithFrame:CGRectMake(102, 0, 185, 40)];
            task.text = @"fasfashfjasfhasfasdjhasgdgasdhjagshjdgashjdgahjsdghjasgasdashgdgjasd";
            task.editable = NO;
            task.scrollEnabled = NO;
            task.userInteractionEnabled = NO;
            task.textColor = [UIColor colorWithRed: 62.0/255.0 green: 85.0/255.0 blue:132.0/255.0 alpha:1.0];
            task.backgroundColor = [UIColor clearColor];
        

        cell.selectionStyle = UITableViewCellSelectionStyleNone;
    

    return cell;

请注意,此代码主要用于示例目的,可以大大减少。此外,您应该像 Richard 建议的那样使用 UITableViewCell 的子类,因为它有助于组织您的代码并使其更具可重用性。

但是不要使用drawRect: 添加子视图。这是不必要的,会影响性能。 drawRect: 仅应在您打算像使用 CoreAnimation 或 CoreGraphics 一样制作真实绘图时使用。添加子视图应在initWithFrame:initWithCoder: 中完成,具体取决于您是否使用Interface Builder。

【讨论】:

我会改成UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: [indexPath section] == 0 ? CellIdentifierForSection0 : CellIdentifierForSection1];【参考方案2】:

记住单元格会被重用,因此每次重用时都会添加子视图。如果要向单元格添加子视图,最好创建UITableViewCell 的子类并在该子类的drawRect: 方法中添加子视图。这样,修改是单元格的一部分,不会在每次重用单元格时添加。

【讨论】:

drawRect: 中添加子视图是一个糟糕的主意。你不应该那样做。来自the docs:you do not need to override this method if your view just displays a background color or if your view sets its content directly using the underlying layer object 我的立场是正确的,代码应该进入初始化程序。现在,UITableVIewCell 原型也可以做很多事情。 我从来没有说过你错了。只是在你的回答中指出不好的做法:)。

以上是关于在 UITableView 内时 UITextField 中的文本重复的主要内容,如果未能解决你的问题,请参考以下文章

使 UITextField 子视图成为 UITableView 中的第一响应者时出错

UITableView 不在 UIScrollView 内滚动

弹出框内的iOS 7 UITableView

在通过数据源创建的 UITextField 中显示占位符文本

需要在 Swift 中的 UITextField 委托方法中引用自定义 UITableViewCell 而不使用 tag 属性

当 UIImageView 在特定区域内时播放声音