読者です 読者をやめる 読者になる 読者になる

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

職業プログラマによる日曜自宅プログラミングの成果たち。と言いつつも最近は公開できる成果が少なくてお悩み中。リアル休日出勤が発生すると更新が滞りがちになる。記事の内容は個人の意見であり、所属している(いた)組織の意見ではない。

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

iOS(iPhone/iPad)

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などで試す際はご注意下さい。

参照