2009-05-17 5 views
10

私はカスタムテーブルセルにカスタムビューを持っています。カスタムビューの特定のプロパティが変更されるたびに- (void)drawRect:(CGRect)rectにビューを再描画する[self setNeedsDisplay]が呼び出されます。このプロパティは、テーブルビューのデリゲートのtableView:cellForRowAtIndexPath:に設定されています。しかし、テーブルビューが画面より大きく、セルを再利用する必要があるときは、setNeedsDisplayのたびにdrawRectが呼び出されません。特に私はテーブルをすばやくフリックするとき。ゆっくりとスクロールしても問題ありません。これは、最初と最後のセルの情報がしばしば正しくないことにつながります。 setNeedsDisplayが常にdrawRectを呼び出すとは限りません

は、ログに私は drawRectへの呼び出しがある setNeedsDisplayへのすべての呼び出しのために、通常はそれを見ることができますが、私はテーブルビューをスクロールするとすぐに setNeedsDisplayから drawRect以上の呼び出しがあります。確かにここには1対1の比率があるはずです。

通常のUIViewで同じカスタムビューを使用し、setNeedsDisplayを呼び出すたびに完全に再描画します。この問題は、テーブルビューとセルを再利用することによって分離されているようです。

ここで何が起こっているのか分かりますか? カスタムビューを強制的に再描画する方法はありますか?

答えて

13

私はこの問題を発見する前にこの問題をほぼ1週間苦労しました。

このカスタムビューへのポインタは、.hファイルではなく.mファイルで定義されており、インスタンス変数ではなくクラス変数になっています。

はい、私は非常に、非常に恥ずかしいです。

1

テーブルを再描画するには、[_table_ reloadData]に電話する必要があります。ない[_table_cell_ setNeedsDsiplay]

+0

私はテーブルを再描画しません。ちょうどカスタムビュー。 – kareman

+1

reloadDataは適切なタイミングであなたのためにsetNeedsDisplayを呼び出します。あなたはフレームワークと戦っているようです。フレームワークが更新するものを決定し、単にtableViewを実装するようにします:cellForRowAtIndexPath: – amattn

+4

reloadDataは、テーブルのすべてのセルを破棄し、再クエリするデータソースと可視セルを再作成させます。それは単なるセルをリフレッシュするのに必要な以上に多くのことです。 – rpetrich

0

ビューがリフレッシュされ、その下の2つの状況があるように聞こえる:テーブルビューのセルを要求している場合は、内部値の変化が(とアップデートを強制的に[self setNeedsDisplay]を呼び出して)、また、描かれた(または再利用された場合)。その状況でそのカスタム表示を明示的に再描画していません。ドキュメントによると

:のtableViewで

テーブルビューのデリゲート:cellForRowAtIndexPathは:セルを再利用する場合常にすべてのコンテンツをリセットする必要があります。

tableviewがセルをリサイクルしている場合、古い値のセルは引き続き返されます。コンテンツが更新されていることを確認するのはあなた次第です。カスタムテーブルセルを設定した方法によっては、ビューが最新であることを確認するためにさらに多くの処理を行う必要があるかもしれませんが、最も簡単なことはカスタムテーブルのセルハンドラーで[myCustomView setNeedsDisplay]を呼び出すことです。

+0

それは私がやっていることです。 in tableView:cellForRowAtIndexPath:私はカスタムビューの基になるデータを変更し、その上でsetNeedsDisplayを呼び出します。ログでは、通常、setNeedsDisplayの呼び出しごとにdrawRectの呼び出しがありますが、テーブルビューをすばやくスクロールすると、drawRectよりsetNeedsDisplayへの呼び出しが増えていることがわかります。確かにここには1対1の比率があるはずです。 – kareman

+1

ビューからセルをスクロールして戻って、変更が有効かどうかを確認してください。 私は昨年、この正確な問題(バグ#6022064:UITableViewsとアクセサリビューの更新)に関するバグレポートを提出したことを思い出しました。彼らはバグを再現できないと答えた。 私の場合、navcontrollerが呼び出され、accessoryViewの色が変更され、setNeedsDisplayが呼び出されますが、戻ったときに更新されませんでした。スクロールしているテーブル外のセルは、正しい色を表示します。 同じことを実行して分離できれば、それを送信してバグを欺くことができます。 – Ramin

6

setNeedsDisplayは、ビューが表示されている場合にのみdrawRect:を呼び出します。それ以外の場合はビューのレイヤーを無効にし、可視になるとdrawRect:が呼び出されます。

テーブルビューをスクロールすると、テーブルビューはビューにセルを追加することを期待してセルを要求します。十分に速くスクロールすると、準備に時間がかかりすぎて準備が整うまでに、配置されるべき位置がオフスクリーンになります。このような場合、テーブルビューはスクロールビューに追加するのではなく、それらを破棄します(したがって、drawRect:は呼び出されません)。

+1

また、setNeedsDisplayは呼び出されたビューにのみ影響します。必要であれば、サブビューを独立して無効にする必要があります。 – rpetrich

+0

大きなテーブルでは音が聞こえますが、テーブルには10行しかありません。同時に8つのテーブルが同時に表示されます。これは、セルが再描画される前にテーブルの下から上に移動した場合にのみ適用されますか? – kareman

+0

ええ、それは大きなテーブルにのみ適用されます。あなたのテーブルでは、8つの表示行はすべてdrawRectを受け取るはずです。もしそうでなければ、おそらくどこかのバグです。あなたのコード(またはまだバグを持っている単純化されたバージョン)を投稿できますか? – rpetrich