iOS Table View入門 #1

2012.02.24

iOSのアプリにおいてリスト形式のUIは非常によく利用されており、とてもなじみ深いUIかと思います。このリストはTable Viewというビューコンポーネントを利用することで実装できますが、このコンポーネントには豊富な機能が実装されています。そこで、テーブルビューの使い方をきちんと押さえるために、その機能や使い方を基本的な部分から見ていきたいと思います。

まず今回は、テーブルビューにデータを表示するまでの手順を追っていきます。開発環境はXCode4.2を、iOS SDKは5.0を使用しています。

プロジェクトの作成

XCodeで新規プロジェクトを作成します。プロジェクトのテンプレート選択画面ではSingle View Applicationを選択します。

デバイスはiPhoneを対象とします。今回はストーリーボードとARCを使用しますので、Use StoryboardとUse Automatic Reference Countingにチェックを入れます。

プロジェクトを作成しましたら、プロジェクトナビゲータから生成されたMainStoryboad.storyboardを選択してストーリーボードを表示します。すると、下図のように初期表示画面のビューが作成されている状態になります。

テーブルビューの作成

今回はテーブルビューのみを使用しますので、シーンの中にあるView Controllerを選択して削除します。プロジェクトナビゲータにあるViewController.hとViewController.mは削除したビューのコントローラクラスですので、こちらも削除しておきます。

次にオブジェクトライブラリからTable View Controllerをドラッグ&ドロップしてシーンを追加します。すると、下図のようにストーリボードにテーブルビューが表示されます。シーンを確認すると、テーブルビューとテーブルビューセルが追加されています。 今回はテーブルビューセルはデフォルトで用意されているものを使用しますので、シーンからTable View Cellを選択して削除してください。

ビューコントローラの作成

次に追加したテーブルビューのコントローラクラスを作成します。プロジェクトナビゲータのプロジェクトフォルダに新規ファイルを追加します。ファイルのテンプレート選択画面でiOS - Cocoa Touchの中にあるUIViewController subclassを選択します。

クラス名をTableViewControllerとし、Subclass ofでUITableViewControllerを選択または入力します。

これでUITableViewControllerを継承したテーブルビューのコントローラクラスが作成され、プロジェクトナビゲータにTableViewController.hとTableViewController.mが追加されました。

ビューとビューコントローラの関連付け

さて、テーブルビューとそのコントローラクラスを作成することができましたが、今の状態ではまだストーリーボードにあるテーブルビューにTableViewControllerクラスがビューコントローラとして関連づけられていません。

ビューとビューコントローラの関連付けをしましょう。ストーリーボードを開き、シーン内のTable View Controllerを選択した状態でアイデンティティインスペクタを開きます。Custom Classセクションの中にClassという項目がありますので、先程作成したTableViewControllerを指定します。これでストーリーボードにあるテーブルビューはTableViewControllerが管理するビューとして設定されました。

表示データの作成

それでは、ビューコントローラを実装していきます。まず、TableViewController.hにNSArray型のフィールドを宣言します。

#import <UIKit/UIKit.h>

@interface TableViewController : UITableViewController {
    NSArray *datas;
}

@end

次に、TableViewController.mに実装をしていきます。 まずは表示するデータの作成です。viewDidLoadメソッドを以下のように修正して下さい。

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    datas = [[NSArray alloc] initWithObjects:@"ひこにゃん", @"はばタン", @"せんとくん", @"くまモン", @"にしこくん", nil];
}

NSArray型のインスタンスを生成してヘッダファイルに宣言したフィールドに格納しています。今回テーブルビューに表示するデータはこの配列の要素になります。

データソース

TableViewController.mの中程に、「#pragma mark - Table view data source」というファンクションメニューのタイトルがあり、そこから「#pragma mark - Table view delegate」までの間にいくつかのメソッドが一部コメントアウトされた状態で記述されているかと思います。これらはUITableViewDataSourceプロトコルで定義されているメソッドです。

UITableViewDataSourceプロトコルはテーブルビューからデータに関する問い合わせを行うのに必要なメソッドを定義したプロトコルで、これを採用したクラスはテーブルビューのデータを管理することができます。このデータ管理クラスのオブジェクトをデータソースといいます。UITableViewControllerはこのプロトコルを採用しているため、UITableViewControllerやそのサブクラスがデータソースとなることが多いようです。今回ストーリーボードで追加したテーブルビューも、デフォルトでビューコントローラがデータソースに指定されています。

さて、UITableViewDataSourceプロトコルで定義されるメソッドのうち、今回のサンプルでは以下の3つのメソッドを実装します。

  • numberOfSectionsInTableView:
  • tableView:numberOfRowsInSection:
  • tableView:cellForRowAtIndexPath:

各メソッドを順番に見ていきましょう。

numberOfSectionsInTableView:

numberOfSectionsInTableView:メソッドはテーブルビュー内にあるセクションの数を返します。セクションはテーブルビューのレコードをグループ分けするための仕組みですが、今回はレコードをグループ分けしませんのでセクションは1つになります。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
   return 1;
}

tableView:numberOfRowsInSection:

tableView:numberOfRowsInSection:メソッドは各セクション内の行数を返します。今回はセクションは1つしかありませんので、単純にdatasの要素数を返しています。

UITableViewDataSourceプロトコルを採用した場合は、このメソッドは必ず実装しなければなりません。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return datas.count;
}

tableView:cellForRowAtIndexPath:

tableView:cellForRowAtIndexPath:メソッドはindexPathで示される位置にあるセルオブジェクトのインスタンスを返します。indexPathはNSIndexPath型のインスタンスで、セクションのインデックスをsectionプロパティに、行のインデックスをrowプロパティに格納しています。これによってテーブルビューによって要求されているセルを特定することができます。このメソッド内では、セルオブジェクトのインスタンスの生成または取得を行い、セルオブジェクトに必要なデータをセットして返します。

UITableViewDataSourceプロトコルを採用した場合は、このメソッドは必ず実装しなければなりません。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
    }
    
    cell.textLabel.text = [datas objectAtIndex:indexPath.row];
    
    return cell;
}

ソースコードを詳しく見てみます。

3行目はセルの再利用識別子を定義しています。この文字列は、テーブルビューがセルオブジェクトのインスタンスを再利用する際にセルオブジェクトの種類を識別するためのものです。再利用識別子を割り当てられたセルオブジェクトはテーブルビューの内部キューに格納され、同じ再利用識別子のインスタンスが要求された際にデータソースに渡されて再利用されます。

5行目は再利用識別子を指定してテーブルビューの内部キューからインスタンスを取得する処理になります。内部キューにプールされたインスタンスがない場合等、ここでインスタンスが取得できない場合には、7行目で新しいセルのインスタンスが生成されることになります。reuseIdentifierパラメータに3行目で定義した再利用識別子が渡されているので、ここで生成されたセルオブジェクトのインスタンスはこの再利用識別子でテーブルビューによって管理されることになります。

また、インスタンス生成時にinitWithStyleパラメータに渡しているUITableViewCellStyleDefaultは定数でセルスタイルの種類を表しています。下図は、デフォルトで用意されているセルスタイルのサンプルです。

この図は、上から順に以下のセルスタイルを使用した例となっています。

  • UITableViewCellStyleDefault
  • UITableViewCellStyleSubtitle
  • UITableViewCellStyleValue1
  • UITableViewCellStyleValue2

すべてのセルスタイルはメインとなるラベルを持っています。その他に、UITableViewCellStyleValue2以外の3つは画像を表示することができ、UITableViewCellStyleDefault以外の3つはサブタイトルや詳細として利用できるラベルをもう一つ持っています。それぞれレイアウトは決まっていますので、これ以外のレイアウトやパーツを持つセルを表示したい場合はセルをカスタマイズする必要があります。

10行目でセル上のUILabelにdatasから取り出した文字列がセットされて、セルの設定が完了します。

実行結果

これで実装が終わりましたので、iPhoneシミュレータ上で実行してみましょう。実行結果です。

datasにセットした文字列がテーブルビューに表示されているのが確認できるかと思います。データを表示するだけならとても簡単にできますね。次回は、テーブルビューの2種類のスタイルとセクションの使い方を見ていきたいと思います。

参考サイト

iOS Developer Library - 日本語版