今回はUITableViewCellの再利用時に癖の強い動作を見つける事ができましたので、その事について書こうと思います。


UITableViewは基本的に、メモリ効率化のためセルを再利用します。

セルの再利用とは、直前に使用した同タイプのセル情報を用いて表示を行なう事を指します。


1つのテーブル上で2種類のセルを用いる物とします。(便宜上タイプ1、タイプ2とします)

タイプ1、2ともにUITableViewCellクラスを用います。

両者の違いは、detailTextLabelに文字列を設定するかしないかの差のみです。

両者の差を実現するため、セルの再利用時に次の様なコードを記載していました。


if (タイプ1) {

    cell.detailTextLabel = 文字列;

}


タイプ1には文字列を設定し、タイプ2には必要がない為処理を記載していません。

動作確認を行なうと、一見正しくテーブルが表示されます。

タイプ1には詳細文字列が表示され、タイプ2には表示されません。

しかし、テーブルのスクロールを行なった途端、タイプ2に設定してもいない詳細文字列が表示されてしまうのです。


この現象の原因は、先ほど述べた「セルの再利用」に起因します。

タイプ2のセルを表示するため再利用するセルは、直前に使用されたセル情報を元に作られます。

その元情報がタイプ1だった場合、タイプ2では再利用された詳細文字列がそのまま使用される事になります。

解決方法は次のようになります。


if (タイプ1) {

    cell.detailTextLabel = 文字列;

}

else {

    cell.detailTextLabel = nil;

}


セルのタイプにより使用する項目や使用しない項目があると思いますが、共通処理として再利用時にはすべての項目を初期化する処理を組み込んだ方が無難かもしれません。

あるいはUITableViewCellクラスにその辺りの初期化処理を組み込んだラッパークラスを作ってしまうのも良いかもしれません。


また別のアプローチとして、少しでも表示方法の異なるセルの場合は再利用時に区別するということも考えられます。

再利用するセルはタグ情報で区別・指定できますので、今回のケースでもタイプ1、2ごとに区別する事は簡単です。

しかし、再利用元を細分化する事は本来の「セルの再利用によるメモリ効率化」という点から見てあまり良策に思えない気もします。

act2.com