質問: iOS開発においてUITableViewでカスタムセルを使用した場合の高速化について質問です。 カスタムセルはFacebookのタイムラインでいう写真のように、動的に表示が切り替わる箇所が4箇所ほど存在しています。 また当該カスタムセルにはAutoLayoutを使用しています。 現状、検索して把握している処置として以下のようなことは検証済みです。(セルの再利用など当たり前のことは割愛) * 透過を使用しない * 高さをキャッシュする * 画像の加工等は別スレッドで行う ベンチマークを取ると動的に要素を表示したり非表示にするところで重たくなっており、上記のようなことは積み重ねると多少効果はあるのですが、大勢に影響なしという状況です。 (必ずしもそうではないのですが傾向として、非表示→非表示→表示といった場合、3度目の表示が切り替わる場面でとりわけ時間がかかっています) ちなみにAutoLayoutではなくプログラムでViewを生成することも検証しましたが、やはり同じ箇所で動作が重たくなってしまいます。 他社様のアプリを見るとカスタムセルを使用しているであろう場面で、私と同様にカクつくものもあれば、FacebookやTwitterのように動的な要素ながら驚くほどスムーズに動くものもあります。 後者のように動的なセルでも滑らかに動作させたいのですが、どのようなアプローチを取れば可能になるのでしょうか。ご存じの方がいらっしゃれば、ご教示ください。
回答: そちらのコードのどこに遅い原因があるかはコードを読めなければわかりませんが、挙げられた三点を行っているのであれば、じぶんに思いつくのはコンテンツの表示・非表示の切替のために発生する再レイアウトの計算量の軽減です。 そのための方法のひとつは、たったひとつのカスタムセルクラスが柔軟なレイアウトを許容するのではなく、**コンテンツの有無や配置を特定のパターンで決め打ちすることでレイアウトのための計算量を減らしたカスタムセルをパターンごとに複数用意**し、キーとなるコンテンツの有無によって使い分けることです。 例えば、あるサブビューを基点として相対的に他の全てのサブビューの表示位置を計算している場合、そのビューの表示状態を切り替えたが為に他の全てのサブビューの座標や大きさを計算し直すようになっているのであれば、そのビューがある場合、ない場合のふたつのカスタムセルクラスを作って使い分けます。 **使用するカスタムセルをコンテンツの有無で切り替える** ``` - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *cellIdentifier; static NSString *cellIdentifierPlain = @"plain"; static NSString *cellIdentifierWithImage = @"withImage"; Class cellClass; // イメージへのパスのあるなしでカスタムセルクラスを切替 NSString *imagePath = _dataSource[indexPath.row][@"imagePath"]; if (!imagePath) { cellIdentifier = cellIdentifierPlain; cellClass = [MyTableViewCellPlain class]; } else { cellIdentifier = cellIdentifierWithImage; cellClass = [MyTableViewCellWithImage class]; } UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: cellIdentifier]; if (!cell) { cell = [[cellClass alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: cellIdentifier]; } // 共通のコンテンツ cell.textLabel.text = _dataSource[indexPath.row][@"text"]; // 表示・非表示コンテンツ if ([cell class] == [MyTableViewCellWithImage class]) { UIImage *image = nil; // パスからイメージ読む ((MyTableViewCellWithImage *)cell).mainImageView = [[UIImageView alloc] initWithImage: image]; } return cell; } ``` また、セルの高さのキャッシュのみならず、Prototype 及び Flyweight パターンが適用できるリソースをくまなく探してみてください。