Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 可可触感&x2013;UITableView dequeueReusableCellWithIdentifier为我提供了错误的单元格数据_Objective C_Ios_Cocoa Touch_Uitableview - Fatal编程技术网

Objective c 可可触感&x2013;UITableView dequeueReusableCellWithIdentifier为我提供了错误的单元格数据

Objective c 可可触感&x2013;UITableView dequeueReusableCellWithIdentifier为我提供了错误的单元格数据,objective-c,ios,cocoa-touch,uitableview,Objective C,Ios,Cocoa Touch,Uitableview,我试图在UITableViewCell中使用UITextField,如下面的代码所示。似乎当tableview离开屏幕时,单元格中应该包含的一些数据被混淆了。我认为方法[tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier]存在一些问题在tableview离开屏幕后无法给我一个“正确”的单元格。这是什么原因 - (UITableViewCell *)tableView:(UITableView *)ta

我试图在
UITableViewCell
中使用
UITextField
,如下面的代码所示。似乎当tableview离开屏幕时,单元格中应该包含的一些数据被混淆了。我认为方法
[tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier]存在一些问题在tableview离开屏幕后无法给我一个“正确”的单元格。这是什么原因

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

    static NSString *addGroupContactCellIdentifier = @"AddGroupContactCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier];

    if (cell == nil) {

        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                       reuseIdentifier:addGroupContactCellIdentifier];

        if ([indexPath section] == 0) { // Group Name Section

            cell.textLabel.text = @"Name";

            UITextField *groupNameTextField = [[UITextField alloc]initWithFrame:CGRectMake(80, 10, 210, 22)];
            groupNameTextField.textAlignment = UITextAlignmentLeft;
            groupNameTextField.backgroundColor = [UIColor clearColor];
            groupNameTextField.placeholder = @"Type Group Name";

            //groupNameTextField.borderStyle = UITextBorderStyleLine;
            groupNameTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
            groupNameTextField.returnKeyType = UIReturnKeyDone;
            groupNameTextField.autocapitalizationType = UITextAutocapitalizationTypeSentences;
            groupNameTextField.delegate = self;

            [cell.contentView addSubview:groupNameTextField];

        }

    }

    if ([indexPath section] == 1) { // Contacts Section

        cell.textLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"name"];
        cell.detailTextLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"number"];

    }

    cell.accessoryType = UITableViewCellAccessoryNone;

    return cell;    
}
更新:

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

    if ([indexPath section] == 0) { // Group Name Section

        static NSString *groupNameCellIdentifier = @"GroupNameCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:groupNameCellIdentifier];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                          reuseIdentifier:groupNameCellIdentifier];

            cell.textLabel.text = @"Name";

            UITextField *groupNameTextField = [[UITextField alloc]initWithFrame:CGRectMake(80, 10, 210, 22)];
            groupNameTextField.textAlignment = UITextAlignmentLeft;
            groupNameTextField.backgroundColor = [UIColor clearColor];
            groupNameTextField.placeholder = @"Type Group Name";

            //groupNameTextField.borderStyle = UITextBorderStyleLine;
            groupNameTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
            groupNameTextField.returnKeyType = UIReturnKeyDone;
            groupNameTextField.autocapitalizationType = UITextAutocapitalizationTypeSentences;
            groupNameTextField.delegate = self;

            [cell.contentView addSubview:groupNameTextField];
        }

        // Customization


        return cell;

    } else {

        static NSString *addGroupContactCellIdentifier = @"AddGroupContactCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                          reuseIdentifier:addGroupContactCellIdentifier];
        }

        // Customization
        cell.textLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"name"];
        cell.detailTextLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"number"];

        return cell;
    }
}
因此,我将
UITableViewCell
子类化,但它仍然显示出与以前相同的错误。这是我的
tableView:cellforrowatinexpath:
的代码:

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

    static NSString *addGroupContactCellIdentifier = @"AddGroupContactCell";

    if ([indexPath section] == 0) {

        UITableViewCellWithUITextField *cell = [tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier];

        if (cell == nil) {

            //cell = [[UITableViewCellWithUITextField alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:addGroupContactCellIdentifier];

            cell = [[UITableViewCellWithUITextField alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:addGroupContactCellIdentifier textFieldPlaceholder:@"Type Group Name" textFieldDelegate:self];
        }

        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        cell.textLabel.text = @"Name";

        // Need to set the UITableViewCell's textLabel properties otherwise they will cover the UITextField
        cell.textLabel.opaque = NO;
        cell.textLabel.backgroundColor = [UIColor clearColor];

        return cell;

    } else { 

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                          reuseIdentifier:addGroupContactCellIdentifier];
        }

        cell.textLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"name"];
        cell.detailTextLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"number"];

        return cell;
    }
}
第三次编辑(我现在有两个不同的重用标识符,它们似乎给了我想要的结果):

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

    if ([indexPath section] == 0) { // Group Name Section

        static NSString *groupNameCellIdentifier = @"GroupNameCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:groupNameCellIdentifier];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                          reuseIdentifier:groupNameCellIdentifier];

            cell.textLabel.text = @"Name";

            UITextField *groupNameTextField = [[UITextField alloc]initWithFrame:CGRectMake(80, 10, 210, 22)];
            groupNameTextField.textAlignment = UITextAlignmentLeft;
            groupNameTextField.backgroundColor = [UIColor clearColor];
            groupNameTextField.placeholder = @"Type Group Name";

            //groupNameTextField.borderStyle = UITextBorderStyleLine;
            groupNameTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
            groupNameTextField.returnKeyType = UIReturnKeyDone;
            groupNameTextField.autocapitalizationType = UITextAutocapitalizationTypeSentences;
            groupNameTextField.delegate = self;

            [cell.contentView addSubview:groupNameTextField];
        }

        // Customization


        return cell;

    } else {

        static NSString *addGroupContactCellIdentifier = @"AddGroupContactCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                          reuseIdentifier:addGroupContactCellIdentifier];
        }

        // Customization
        cell.textLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"name"];
        cell.detailTextLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"number"];

        return cell;
    }
}

你说得对!这个问题肯定是由于
UITableView
可重用性
特性造成的。苹果以这样的方式做到了这一点,这样你就可以重复使用电池了,而且从性能的角度来看,它工作得非常出色!因此,当您尝试上下滚动时,
indepath
值仍然相同,并且tableView从类中定义的
cellforrowatinexpath
获取数据

解决方案:

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

    if ([indexPath section] == 0) { // Group Name Section

        static NSString *groupNameCellIdentifier = @"GroupNameCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:groupNameCellIdentifier];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                          reuseIdentifier:groupNameCellIdentifier];

            cell.textLabel.text = @"Name";

            UITextField *groupNameTextField = [[UITextField alloc]initWithFrame:CGRectMake(80, 10, 210, 22)];
            groupNameTextField.textAlignment = UITextAlignmentLeft;
            groupNameTextField.backgroundColor = [UIColor clearColor];
            groupNameTextField.placeholder = @"Type Group Name";

            //groupNameTextField.borderStyle = UITextBorderStyleLine;
            groupNameTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
            groupNameTextField.returnKeyType = UIReturnKeyDone;
            groupNameTextField.autocapitalizationType = UITextAutocapitalizationTypeSentences;
            groupNameTextField.delegate = self;

            [cell.contentView addSubview:groupNameTextField];
        }

        // Customization


        return cell;

    } else {

        static NSString *addGroupContactCellIdentifier = @"AddGroupContactCell";
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier];

        if (cell == nil) {

            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
                                          reuseIdentifier:addGroupContactCellIdentifier];
        }

        // Customization
        cell.textLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"name"];
        cell.detailTextLabel.text = [[self.selectedPeoplePickerContacts objectAtIndex:[indexPath row]] objectForKey:@"number"];

        return cell;
    }
}
您需要对
UITableViewCell
进行子类化,并在
-(void)layoutSubview
方法中添加
UITextField

然后,您需要引用此
CustomUITableViewCell
,并使用它来加载TableView


一个有帮助的链接:

这些值混合在一起,因为当您离开屏幕,然后再次重新加载表格时,这些单元格将从内部表格单元格池中删除,但它们不会按照以前在表格中的顺序重新加载。请注意,即使您有一个包含许多行的表并滚动它,也会发生这种混合。解决方案是将文本字段数据存储在“数据源”数组中,然后配置单元格

解释

基本上,代码中存在一个主要的概念缺陷:一旦重新生成单元格,就无法正确配置内容(根本无法配置)。我的意思是,最初,当第一次显示表时,池是空的。因此,需要显示的每个新单元格都会从头开始重新创建(而不是从池中删除);假设您的表可以在屏幕上显示10个单元格,那么前10个单元格将全部从头创建,并带有空文本字段。 然后开始在这些字段中输入文本,所有操作都正常。 在某一点上,您开始滚动单元格:发生的情况是,位于顶部的所有单元格将从屏幕上消失,并存储(排队)在表池中,以及它们的文本字段及其编辑的内容;假设您在第0行对单元格进行排队。当一个新的单元格需要显示在屏幕底部时,代码要做的第一件事就是尝试对单元格进行消隐。现在,这一次池中有一个单元格(第0行的单元格),该单元格将从池中检索并放置在表中,包括第11行的TEXTFIELD内容。所以“神奇地”你会在另一行11的第0行找到一个被编辑的文本。此外,单元格是以稀疏的顺序从池中检索的,因此在许多文本字段编辑和滚动之后,您将有一个完整的混合

解决方案,这就是代码中出现错误的原因:一旦创建或删除单元格,就对其进行配置,即设置textfield内容。如何检索文本字段内容?存储在数组中。这就是为什么视图控制器是一个“数据源”,因为您需要源数据来填充表。由于这种去队列机制,在表中存储数据是错误的。例如:


groupNameTextField.text=[myTextFieldContentArray objectAtIndex:indexPath.row];
另一个解决方案,但我不建议,是为每个单元格分配一个唯一的标识符,即:


NSString *myCellId = [NSString stringWithFormat:@"CellID_%d_%d",indexPath.section,indexPath.row];
在这种情况下,所有的细胞将被赋予不同的名称,你永远不会混淆它们。 此解决方案大部分时间都有效,但由于以下两个原因不鼓励使用: A.这是非最优的,因为您不重用单元,所以这会为类似的单元占用额外的内存
B您不能保证每个单元都有效地排队,所有这些逻辑都在表中,并且不向开发人员公开,因此您可能需要在需要时每次重新生成单元(性能损失)。

如一些人所建议的,不需要子类化

但是您不能在“if(cell==nil){”中使用类似“if([indepath section]==0){”这样的逻辑,因为它只在第一次创建单元时被调用,并且将在后续循环的其他索引中重新使用

相反,您需要使用两个不同的单元标识符,以便为第0节设置的单元不会在表中的其他位置重复使用。在将单元出列之前,请将if([indexPath section]==0){放入单元格,并为第0节和后续的节单元使用不同的单元标识符


此外,请确保在“if(cell==nil){”之外执行任何特定于indexpath的操作,以便在每次重复使用单元格时应用它,而不仅仅是在第一次创建单元格时应用它。

我不是UITableViewCell的子类。但我见过其他处理它的方法(我假设没有问题)子类化是摆脱可重用性问题的唯一解决方案!!@PeterWarbo当然。没错!这将摆脱可重用性问题。但根据经验……我会再次选择
子类化
,因为从长远来看,这将帮助您解决问题!