2012-01-19 9 views
0

UITextFieldUITableViewCellの内部で使用しようとしています(下のコードを参照)。テーブルビューがスクリーンから外れると、セル内にあるはずのデータが混在しているように見えます。私は、テーブルビューが画面から消えた後に、私に「適切な」セルを与えることができないメソッド[tableView dequeueReusableCellWithIdentifier:addGroupContactCellIdentifier];で起こっている問題があると思います。これの理由は何ですか?Cocoa-Touch - UITableView dequeueReusableCellWithIdentifierが間違ったセルデータを返しました

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

UPDATE:

だから私はUITableViewCellをサブクラスが、まだそれは前と同じエラーを示します。これは、今tableView:cellForRowAtIndexPath:のための私のコードです:

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

サードEDIT(私は私に私の望んでいた結果が得られているように見える今、2つの異なるreuseIdentifiersを持っている):

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

答えて

1

いくつか提案されているように、サブクラス化は必要ありません。

しかしif([indexPath section] == 0){"if(cell == nil){"の内部では、セルが最初に作成されたときだけ呼び出されるため、その後のリサイクルでは他のインデックスでも使用されます。

代わりに2つの異なるCellIdentifierを使用する必要があります。そのため、セクション0用に設定したセルはテーブルの他の場所で再利用されません。 if([indexPath section] == 0){セルをデキューする前に、セクション0と後続のセクションセルに異なるセル識別子を使用します。

また、「if(cell == nil){」の外側にindexpath固有の属性を指定して、セルが最初に作成されたときだけでなく再利用されるたびに適用されるようにしてください。

0

あなたは正しいです!問題は間違いなくUITableViewreusability機能に起因しています。アップルは、あなたが細胞を再利用することができるように、そのようにしました。そして、それはパフォーマンスの立場で美しく動作します!したがって、上下にスクロールしてみると、indexPathの値は同じになり、tableViewはクラスで定義したcellForRowAtIndexPathのデータを取得します。

ソリューション:

あなたのUITableViewCellのサブクラスを作成し、あなたの-(void)layoutSubviews方法でUITextFieldを追加する必要があります。

次に、このCustomUITableViewCellを参照し、それを使用してTableViewを読み込む必要があります。

役立つリンク:あなたが画面外に行くし、その後、細胞を内部テーブルのセルからプールdequedされているが、それらは同じ順序で再ロードされていない、再びテーブルをリロードするときので Read this !

+0

私はむしろUITableViewCellをサブクラス化しません。しかし、私は別のものを見てきました(ちょっとした問題なし)http://stackoverflow.com/q/409259/294661 –

+0

サブクラス化は、再利用性の問題を取り除く唯一の解決策です! – Legolas

+0

私はよく分かりませんが、私は再利用可能性の問題を取り除いたと思います。私の編集を参照してください... –

0

値が混ざっています以前はテーブルにいた。多くの行を含む表があり、それをスクロールしてもこの混合が起こることに注意してください。解決策は、テキストフィールドデータを「データソース」配列に格納し、セルを構成することです。

説明】基本的に、あなたのコード内で一つのメイン概念的な欠陥があります:あなたは、細胞を再生した後、あなたは(あなたがすべてでそれを設定していない)適切にコンテンツを設定しないでください。つまり、テーブルが最初に表示されたとき、最初はプールが空です。したがって、表示する必要のある新しいセルは、最初から再作成されます(プールからは削除されません)。あなたのテーブルが画面に10個のセルを表示できるので、最初の10個のセルはすべてゼロから空のテキストフィールドで作成されます。 これらのフィールドにテキストを入力すると、すべて正常に動作します。 ある時点で、セルのスクロールを開始します。画面上部にあるすべてのセルが画面から消え、テキストフィールドとその編集内容で表プールに格納されます(キューに入れられます)。新しいセルを画面の最下部に表示する必要がある場合、コードが最初に行うことは、セルをデキューしようとすることです。今度は、プール(行0にあるセル)にセルがあり、このセルはプールから取得され、11行目のTEXTFIELD CONTENTを含むテーブルに配置されます。それで、 "魔法のように"行0で編集されたテキストが見つかるでしょう。プールから疎な順番でセルが検索されるだけでなく、多くのテキストフィールドの編集やスクロールの後、完全な混合ができます。

解決方法これは、コードのバグの原因です。セルが作成または確認されたらすぐに設定して、テキストフィールドの内容を設定します。テキストフィールドコンテンツを取得するには?配列に格納する。これは、ビューコントローラが「データソース」である理由です。これは、データをソースにしてテーブルを埋めるためです。このデキューメカニズムのため、テーブルにデータを格納するのは間違いです。例:この場合


NSString *myCellId = [NSString stringWithFormat:@"CellID_%d_%d",indexPath.section,indexPath.row]; 

全ての細胞を、enquedされます。


groupNameTextField.text=[myTextFieldContentArray objectAtIndex:indexPath.row]; 

別の解決策が、私はそれを示唆していない、つまり、各セルに固有の識別子を割り当てることですあなたはそれらを混ぜ合わせることはありません。 このソリューションはほとんどの場合動作しますが、2つの理由で推奨されません。 a。セルを再利用しないので、最適ではないため、類似のセルに余分なメモリが必要になります。 b。あなたは、各セルが効果的にキューに入れられていることを保証されているわけではありません。このロジックはすべてテーブルの内側にあり、開発者には公開されません。したがって、必要なときにセルを再生成する必要があります。

関連する問題