職業プログラマの休日出勤

職業プログラマによる日曜自宅プログラミングや思考実験の成果たち。リアル休日出勤が発生すると更新が滞りがちになる。記事の内容は個人の意見であり、所属している(いた)組織の意見ではない。

Static Cells で楽々UITableViewプログラミング

iOS5から Storyboards が導入され、それと同時にStaticCellsが登場しました。「試しに」StaticCellsを利用することはありましたが、分からない事も多く、本気で使うのはためらっていました。この記事ではStaticCellsを本気で使うために必要なものなどを紹介したいと思います。

What's StaticCells ?

多くの方はiOSの開発を始めたばかりの頃に「InterfaceBuilder上で全てのセルの設定を行いたいのに、セルはコードからしか作れない!」と思われたことがあるでしょう。StoryboardsのStaticCellsが、この願望への答えになります。次に挙げるような特性を持ちます。

StaticCellsを使うメリット
  • IB上でほぼ全てのセル設定を行うことができる
  • 書くコードの量は少なくなる(ことが多い)
StaticCellsでできないこと/激ムズになること
  • Storyboardsの利用が必須になる ⇒ iOS5以降のみの対応になり、iOS4系等は切り捨て。
  • セルの数を増減させることはできない(っぽい。たぶん。)。

実際にStaticCellsを使ってみる

このような特性があることを分かった上でStaticCellsの利用を決心したら、実際に使ってみましょう。

プロジェクトの作成と設定

新規プロジェクト作成をメニュー等から選択し、「Master-Detail Application」を選択します。昔は「Navigation Based Application」という名前だったような気もしますが、自信はありません。
f:id:t_motooka:20120326002248p:image

プロダクト名を設定し、「Use Storyboards」にチェックを入れます。「Next」を押すと保存先を聞いてくるので適当に。
f:id:t_motooka:20120326002249p:image

PrototypeからStaticCellsへ

早速、本題の修正からやってしまいましょう。storyboardファイルを開くと↓のような画面になります。スクロールすると Master View Controller が見えるので、こいつのTableViewを Dynamic Prototypes から Static Cells に変更することにしましょう。
f:id:t_motooka:20120326002250p:image
画面右上のプルダウンメニューを使って「Dynamic Prototypes」を「Static Cells」に変更すると…
f:id:t_motooka:20120326002251p:image
おおおおお!セルの構成が変わりました!これらのセルのラベルを変更してsegue(ViewController間をつなぐ線)を設定すると、こんな感じになりました。segueのIdentifierは3個とも別々のものにしておきましょう。
f:id:t_motooka:20120326002252p:image
これでIB作業は終了です。StaticCellsそのものはこれで完成なのです(旧来型よりはずっと簡単ですね)が、少しだけコードも修正する必要があります。

コード MasterViewController.m の修正

主に、このような修正をする必要があります。理由や詳細などはサンプルコードのコメントに記載しているのでご覧下さい。削除系の修正ばかりなので簡単ですね(きっと)。

  • - (void)viewDidLoad で作成しているセル編集系ボタンの設置作業を削除(コメントアウト。以下同。)します。
  • - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView をメソッド丸ごと削除します。
  • - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section をメソッド丸ごと削除します。
  • - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath をメソッド丸ごと削除します。
  • - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath をメソッド丸ごと削除します。
  • - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath をメソッド丸ごと削除します。
  • - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender を、segueのIdentifierに合わせて調整します。基本的には、DetailViewControllerに渡すデータの処理をしています。
動かしてみる

f:id:t_motooka:20120326002830p:image
おおお!動きましたね。ほぼIB作業とコード消し作業だけでここまで動くものが作れるのです!

考察:なぜStaticCellsが流行らないのか

いくつかの制限事項はあるものの、StaticCellsはこのように便利なものです。しがしながら、ネット上のStaticCellsの情報は少ない(⇒流行っていない)ように見えます。この理由としては次のものが考えられます。

  • iOS5より古いOSに対応できない
  • プロジェクト/クラステンプレートにStaticCells利用を前提としたものが無い

前者は時間が解決する問題かとは思いますが、後者はバラ撒けばStaticCellsの普及につながりそうな気もします。先日の勉強会でお教え頂いた カスタムテンプレート作成(英語) を参考にしたいところです。

今後検証してみたいこと

時間があればこんなことも試してみたいです。

  • セルの数が増えてきたとき、Prototype方式(StaticCellsではない従来型の方法)とどちらが高速に動作するのか。また、どちらがメモリ戦略上有効なのか。
  • 仮に、セルの数が多い場合はPrototype方式が有利だった場合、いくつぐらいまではStaticCellsが実用に耐えるのか。
  • どうにかしてセルを追加/削除してみる。

検証環境

筆者が検証に利用した環境は以下の通りです。これとは異なるバージョンのOSやXcodeなどで試す際はご注意下さい。

参照