[iOS] UITableViewのセルをカスタマイズする [4月からはじめるiPhoneアプリ #3]

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

こんにちは!

前回のUITableViewのデータを検索するから引き続き、UITableViewについて書きます。

今回はテーブルビューセルのカスタマイズについて覚えましょう。

この記事は4月からiOSアプリエンジニアとして働く方、転向する方を対象としています。

「iOSアプリケーションを1度でも作ったことがある」、もしくは「入門書を1冊読んだことがある」方には特に参考になるような記事になると思います。

マジックナンバーは極力使わない

毎回小ネタを挟んでいるので、今回は マジックナンバー について書きます。

マジックナンバーとは

マジックナンバー (プログラム)

プログラムにおけるマジックナンバー(魔法数字)とは、何らかの識別子として用いられるプログラム中に書かれた具体的な数値(「10」「123」など、数字によって記述される値)である。

そのプログラムの製作者は数値の意図を把握しているが、他のプログラマーまたは製作者本人がマジックナンバーの意図を忘れたとき閲覧すると「この数字の意味はわからないが、とにかくプログラムは正しく動く。まるで魔法の数字だ」という皮肉を含む。

Wiki - マジックナンバーより

「定数」(URL・特定のViewの決められたサイズ・Storyboardで手打ちしたID) はこれに該当するでしょう。

自分の書いたソースコードを他人が編集する場合、これらをいち早く認識できるかによって開発速度が変わります。

また自分の書いたソースコードに改修を加える場合も、複数の箇所で同じURLなどを記述している場合は、一個のファイルにまとめておくとAPIサーバのテスト・本番の切り替えなどが素早く対応しやすいです。

手法としてはファイル名 + Const(ant)ファイルとして、定数だけを定義したクラスファイルを一つ作るのが広く一般的だと思います。

今回はxibファイルを作るので、xibのクラスIDをこの形式で別途定義しましょう。

Storyboardやソースは前回のものをベースに追加していきます。

まずはグループを作ります。グループはプロジェクト内における階層構造のようなものです。フォルダの様なアイコンですが、プロジェクトファイル内にフォルダを作っているわけではありません。

グループは作りたい階層を選択して

右クリック(Control + クリック) → New Group

で作成できます。

今回はこのように作りました。

customcell_01

TableViewConst.hはNSObjectのサブクラスを新規作成後、.mファイル(実装ファイル、定数の定義のみなので実装は要らない。)は必要ないので削除しました。

こちらに後ほど定数を追加していきます。

カスタムセルを作る

カスタムセルはUITableViewCellクラスを継承したサブクラスを定義するのも良いですが、今回はxibファイルを用いた方法でグラフィカルに作成していきます。

先ほど作成したTableViewCellグループにxibファイルを作成します。

customcell_02

グループを右クリック(Control + クリック) → New File → User InterfaceタブのEmpty → Next → Next → ファイル名.xib

で作成できます。ファイル名はTableViewCustomCell.xibにしました。

このファイル名称は定数定義ファイルに定義するため、コピーしておいて下さい。

xibファイルを選択するとはじめは真っ白な画面になります。

この真っ白なところにテーブルビューセルをドラッグして持って来ましょう。

customcell_03

今回はこちらにサムネイル画像と名前・セル番号を追加します。

customcell_04

見た目が完成したらTableViewCellグループにUITableViewCellクラスを継承したサブクラスを作成します。

customcell_05

その後、xibファイルに作成したクラスを適用します。

customcell_06

配置した画像やラベルのプロパティをIBOutletで紐付けします。

customcell_07

そして、カスタムセルの高さを返すクラスメソッドを定義します。

セルの高さはこちらから確認できます。

customcell_08

CustomTableViewCell.hに追加

+ (CGFloat)rowHeight;

CustomTableViewCell.mに追加

+ (CGFloat)rowHeight
{
    return 60.0f;
}

カスタムセルの作成はこれで終わりです。

作成したカスタムセルを呼び出す

先ほど作成した TableViewConst.h ファイルに戻ります。こちらにxibファイルで作成したカスタムセルのID(先ほどコピーしたファイル名から.xibを除いたもの)を定義しましょう。

#import <Foundation/Foundation.h>

/**
 *  サムネイル・デバイス名・セル番号で構成されたカスタムセルのIDです。
 */
static NSString * const TableViewCustomCellIdentifier = @"TableViewCustomCell";

定数はプリプロセッサの#define句でも書けますが、明確に型が指定できる

static 型名 (参照型であれば * ) const 変数名

書式にしましょう。コンパイル時の型チェックもできるので、予期しない値が入ることでのエラー防止にも繋がります。

ViewController.m に戻り、テーブルビューの実装を再開します。

まずは作成したカスタムセルクラス、定数クラスをインポートしましょう。

#import "ViewController.h"
#import "CustomTableViewCell.h"
#import "TableViewConst.h"

変更する箇所は以下3カ所です。

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    // デリゲートメソッドをこのクラスで実装する
    self.tableView.delegate = self;
    self.tableView.dataSource = self;

    self.searchDisplayController.delegate = self;

    // テーブルに表示したいデータソースをセット
    self.dataSourceiPhone = @[@"iPhone 4", @"iPhone 4S", @"iPhone 5", @"iPhone 5c", @"iPhone 5s"];
    self.dataSourceAndroid = @[@"Nexus", @"Galaxy", @"Xperia"];

    // カスタマイズしたセルをテーブルビューにセット
    UINib *nib = [UINib nibWithNibName:TableViewCustomCellIdentifier bundle:nil];
    [self.tableView registerNib:nib forCellReuseIdentifier:@"Cell"];
    [self.searchDisplayController.searchResultsTableView registerNib:nib forCellReuseIdentifier:@"Cell"];
}

// ...省略

/**
 *  テーブルに表示するセルを返します。(実装必須)
 *
 *  @param tableView テーブルビュー
 *  @param indexPath セクション番号・行番号の組み合わせ
 *
 *  @return セル
 */
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    // ...省略
}

#pragma mark - UITableViewDelegate methods

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return [CustomTableViewCell rowHeight];
}

セルの作成時のif (!cell)チェックがなくなった事により少しスッキリしました。

何故nilチェックがいらないかというのを詳しく知りたい方は

Storyboard上のUITableViewCellをxibで作る場合はregisterNib:forCellReuseIdentifier:メソッドが便利

こちらが参考になります。

cell.の後に先ほどxibに紐付けたプロパティをセットすることができますので好きな画像をセットすることが簡単にできます。

以下のように表示されれば完成です。

customcell_09

ここまでのソースが断片的になってきましたので、GitHubへ公開しました。

まとめ

今回はテーブルビューのカスタムセルについて書きました。

ポイントは

[self.searchDisplayController.searchResultsTableView registerNib:nib forCellReuseIdentifier:@"Cell"];

の部分です。

UISearchDisplayControllerにもUITableViewCellが潜んでいるため、こちらにもカスタムしたセルをセットしておかないとアプリが落ちますので気をつけて下さい。

xibファイルはXcode4.6からObjective-Cを始めた私にはかなり違和感のあるファイルでした。しかし使ってみるとカスタムViewをグラフィカルに定義できるので、レイアウトが非常に面倒なUITableViewCellにはうってつけでした。

画面数が多いアプリケーションだとカスタムセルがたくさんできてしまい、管理が煩雑になってしまいます。

今回使った定数ファイルは1行しか記述していませんが、「この種類のViewのIDは後々増えそうだな〜。」とか、「複数の画面で同じカスタムCellを使ってるな〜。」といった場合は活用しましょう。

次回は 「UITableViewのセルをタップした時に詳細画面を表示する。」 を書こうと思います。