UITableViewについて(おもにdelegateメソッド)
今日は最近よく使うUITableViewについて書こうと思います。
https://developer.apple.com/Library/ios/documentation/UIKit/Reference/UITableView_Class/index.html
UITableView(以下テーブルビュー)についてはobjective-cの中で最も良く使うコンポーネントではないかと思います。
ビューと名前がついていることからもUIViewのサブクラスのビューです。
このビューはセル(UITableViewCell)と呼ばれるインターフェース部品を要素としたテーブルです(そのまま^^;
一般にテーブルビューを作成するには二つの方法があります。
①UITableViewControllerを継承したViewControllerを作成する
②ViewControllerの中でUITableViewを保有する
今回はより汎用性の高いViewControllerの中でテーブルビューを保有する方法②について説明しようと思います。
具体的な方法は以下の通りです。
①headerファイルの宣言部でインターフェースを実装していることを宣言する
これはテーブルビューのデリゲートメソッド(セルの内容や個数の定義、変更を行るメソッド)を認識するためです。
@interface XXXViewController : UIViewController<UITableViewDataSource,UITableViewDelegate>
ここは他のデリゲートメソッドを使用する時といっしょです。
②テーブルビューを定義
使い方によってグローバルに定義する場合とローカルに定義する場合がありますが、今回は必要最低限ということでローカルに定義します。
その場合、例えばviewDidLoadの中で
UITableView *myTable = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
等と宣言、定義してあげます。
第一引数は表示するテーブルビューのサイズです。
この場合、画面いっぱいに表示しています。
台に引数はテーブルのスタイルで、UITableViewStylePlainと
UITableViewStyleGroupedを選びます。
例のように後者を選んだ場合はセクションと呼ばれるセルのグループ毎に表示します(具体的にはスクロールしてもヘッダーと呼ばれるビューが常に表示されるようになる)
どのセルがどのグループに属するかも定義できます。
③テーブルビューをaddSubview
②で作成したテーブルビューを表示させます。
例えば、
[self.view addSubview : myTable]
とすればself.viewに配置されます。
④宣言したテーブルビューをデリゲートメソッドに関連づける
①で関連づけたインターフェースのデリゲートメソッドと関連づけます。
myTable.dataSource = self;
myTable.delegate = self;
これだけです。それぞれのインターフェースと対応しています。
⑤デリゲートメソッドの定義
以下のようにたくさんあります。
A.dataSource
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
セクション内のセルの個数を返します。
必ず定義しなければなりません。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
ここで具体的な内容を記述したセルを返します。
必ず定義しなければなりません。
ここでの注意としてセルに部品(ボタンやラベル等)を配置する場合は
セルに直接addSubviewするのではなく、
セルのcontentViewに対してaddSubviewするところです。
例えば
[cell.contentView addSubview: btn];
のように。
-(NSInteger)numberOfSectionsInTableView:
(UITableView *)tableView
セクションの個数を返します。
必須ではありません。
-(NSString *)tableView:
(UITableView *)tableView
titleForHeaderInSection:(NSInteger)section
セクションのヘッダータイトルを返すように実装する
必須ではありません。
-(NSString *)tableView:
(UITableView *)tableView
titleForFooterInSection:(NSInteger)section
セクションのフッタータイトルを返すように実装する
必須ではありません。
-(void)tableView:
(UITableView*)tableView commitEditingStyle:
(UITableViewCellEditingStyle)
editingStyle forRowAtIndexPath:
(NSIndexPath*)indexPath
編集モード時で、Delete、Insertされた時に呼び出されます。
※Delete時はcommitEditingStyleにUITableViewCellEditingStyleDeleteが渡されます
※Insert時はcommitEditingStyleにUITableViewCellEditingStyleInsertが渡されます。
-(void)tableView:
(UITableView*)tableView
moveRowAtIndexPath:(NSIndexPath*)
fromIndexPath
toIndexPath:(NSIndexPath*)toIndexPath
編集モード時で、セルが移動された時に呼び出されます。
※fromIndexPathに移動前のNSIndexPath、toIndexPathに移動後のNSIndexPathが渡ってくる。
B.delegate
-(CGFloat)tableView:
(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
セルの高さを浮動小数型返します。
必須ではありません。
-(CGFloat)tableView:(UITableView *)tableView
heightForHeaderInSection:(NSInteger)section
同様にセクションヘッダーの高さを返します。
-(CGFloat)tableView:(UITableView *)tableView
heightForFooterInSection:(NSInteger)section
セクションフッターの高さを返します。
-(void)tableView:
(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath
セル毎にタップ時の反応を記述します。
セルをボタンの代わりのようにも出来ます。
-(void)tableView:(UITableView *)tableView
accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
アクセサリボタンと呼ばれる部品をタップした時の反応を記述します。
これで一通り書いたかと思います。
忘れているものもあるかもしれないのですが。。^^;
個人的にtableView: cellForRowAtIndexPath:でセルを再利用する時が少し面倒だったかもしれませんが、ここら辺はiOS6からiOS7になるときに大幅に楽になったようです。
あと、iOS7からiOS8になってからセルのサブビュー構造が変わったことがくせ者でした。
例えば、[cell.contentView addsubview:btn1]とした時、
iOS7:UITabeViewCell->UITableViewCellContentView->UITableViewCellScrollView->btn1
となっていたのが
iOS8:UITabeViewCell->UITableViewCellContentView->btn1
というふうになり、構造が変わっていました。
セルを動的に部品管理(例えば個別セルに設置した部品に対してremoveFromSuperview)する時は上記を気をつけなくてはいけないようです。
次回はUICollectionViewについて書いてみようと思います。