2011-12-04 5 views
0

US状態データを含む辞書要素の配列をUITableViewにロードしていて、ユーザーがオフスクリーン項目までスクロールすると重複行が発生します。 8行目で重複し、行2が行9で重複している、などUITableViewCellをUILabelのサブビューから構築する際の重複行を回避する方法

私はSO以下の質問を検討し、(成功せずに)彼らの提案の一部を実装しました:

2994472 - 私のUITableViewは重複行を持ってい

7056578 - UITableViewは、スクロール

UITableViewCellはUILabelsから作成されたカスタムコンストラクションです。ここにcellForRowAtIndexPathのコードがあります。

00 const int ABBREVIATION = 1, STATE = 2 // Declared outside cellForRowAtIndexPath 


01 static NSString *CellIdentifier = @"Cell"; 
02  
03 UILabel *abbreviation, *state; 
04  
05 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
06 if (cell == nil) { 
07  cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault   
08    reuseIdentifier:CellIdentifier]; 
09   
10  abbreviation = [[UILabel alloc] initWithFrame:CGRectMake(7.0, 1.0, 34.0, 30.0)]; 
11  abbreviation.tag = ABBREVIATION; 
12  abbreviation.font = [UIFont fontWithName:@"Helvetica-Bold" size:20.0]; 
13  abbreviation.textAlignment = UITextAlignmentLeft; 
14  abbreviation.textColor = [UIColor blackColor]; 
15 
16  state = [[UILabel alloc] initWithFrame:CGRectMake(42.0, 1.0, 158.0, 30.0)]; 
17  state.tag = STATE; 
18  state.font = [UIFont fontWithName:@"Helvetica-Bold" size:20.0]; 
19  state.textAlignment = UITextAlignmentLeft; 
20  state.textColor = [UIColor blackColor]; 
21 
22  [cell.contentView addSubview:abbreviation]; 
23  [cell.contentView addSubview:state]; 
24  
25  [cell setAccessoryType:UITableViewCellAccessoryDetailDisclosureButton]; 
26  [cell setSelectionStyle:UITableViewCellSelectionStyleNone]; 
27 } 
28  
29 abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"]; 
30 state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"]; 
31  
32 return cell; 

2994472のアドバイスに従って、27行目と28行目を変更して3項演算子を使用します。動作しませんでした

29 abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"] ? 
         [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"] : 
         @""; 

30 state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"] ? 
        [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"] : 
        @""; 

、重複はまだ実際のサブビューにドリルダウンするラベルのテキストを設定する際にどのような問題を解決するように見えることはUILabelタグを参照している行に8

を開始起こります。

29 ((UILabel *)[cell viewWithTag:ABBREVIATION]).text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"]; 
30 ((UILabel *)[cell viewWithTag:STATE]).text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"name"]; 

このようにセルのサブビューが参照されると、UITableViewの行の複製が消えます。

+0

最初のバージョンでは、変数がセルにリンクされているため、変数の省略形と状態の最後のallocedバージョンを保持しているという事実からエラーになります。しかし、あなたは答えを持っています、質問がありましたか? – gregory

+0

最後に割り当てられた略語と状態をリリースすることをお勧めします(私はこのファイルに対してARCを有効にしてiOS 5を使用しています)。また、他の誰かが同様の状況に陥った場合に備えて私はこれを投稿しました。 – billmaya

+0

addSubViewで追加した後にリリースするだけです。addSubViewはそれを保持し、メモリ管理をuitbaleviewコードに渡して解放します。あなたの掲示されたコードのメモリ使用量は、ますます増え続けるでしょう。 – gregory

答えて

1

元の質問で解決策を投稿することはできましたが、最初は重複したセルの状況がなぜ起こったのか不思議でした。

セルに表示されている値の横に、状態値と省略値のテキスト値を書き出して、さらに調査しました。

(A) NSLog(@"%@", state.text); 
(B) NSLog(@"%@", ((UILabel *)[cell viewWithTag:STATE]).text); 

表示された結果は興味深いものです。

(A)    (B) 
Iowa    Iowa 
New Hampshire  New Hampshire 
South Carolina South Carolina 
Florida   Florida 
Nevada   Nevada 
Colorado   Colorado 
Minnesota   Minnesota 
(null)   Iowa 
(null)   New Hampshire 
(null)   SouthCarolina 
(null)   Florida 

スクロールアップして追加の状態を表示すると、(null)値が表示されます。

私は、スクロールダウンが起きたときに、29行目と30行目の元のコードが2つのインスタンス変数のテキスト値を設定しようとしていると考えています。

29 abbreviation.text = [[self.primaries objectAtIndex:indexPath.row] objectForKey:@"abbreviation"]; 
30 state.text = [[self.stateInfo objectAtIndex:indexPath.row] objectForKey:@"name"]; 

しかし、それらは自動的にARCによって参照解除されているため、それらはもはや存在せず、設定できず、値nullを返します。ただし、元の値を含むセルは「デキュー」され、古いデータと再利用され、重複が表示されます。

私はこの仮説を完全に根拠がないと私に教えてください。

+0

あなたは100%正しいです。古いセル**を古いデータで再利用します。セル内のすべてを再初期化する必要があります。ありがとう! –

0

それはあなたのifブロックがスキップされるようにdequeueReusableCellWithIdentifier:は、既存のテーブルビューセルを返した場合のように見えますが、あなたのabbreviationstate変数が設定されていません。したがって、この場合(スクロールを開始して再利用されたセルを表示すると発生する)、abbreviationstateは関数の最後にはnilとなり、再利用されたセルのラベルは期待通りに更新されません。 elseブロックを使用して、cellの正しいサブビューを指すように略語と状態変数を設定します。

+0

しかし、略語と状態のテキスト値を設定するコード行は、if(cell == nil)ブロックの外側です。あなたが言うことは真実です。既存のセルを再利用すると、作成コードはスキップされますが、値設定コードは常に実行されます。 あなたはセルを再利用しているので、再利用されたセルのUILabelサブビューへの参照はゼロでアクセスできないと言っていますか? – billmaya

+0

あなたの質問を読んだときに、質問の最下部にあるコードの 'viewWithTag'行が欠落していたのかもしれません。これらの2つのviewWithTagステートメントは、あなたが 'else'ブロックに入れることを提案したものです。おそらく、 'viewWithTag'呼び出しはnilを返すでしょうが、ここではメモリから外していますが、' [cell viewWithTag:ABBREVIATION] 'の代わりに' [cell.contentView viewWithTag:ABBREVIATION] 'などを使う必要があります。 –

+0

[cellViewWithTag:ABBREVIATION]と[cell.contentView viewWithTag:ABBREVIATION]の両方が機能します。 – billmaya

関連する問題