カスタムセルにボタンを貼りつけた時の処理パターンの紹介。
処理パターン
ボタンのタップイベントをどこで受け取るべきか。カスタムセルで受け取るのも手だが単なるビューなのでモデルとのつながりが無い。モデルとの接点があるのは ViewController なのでここでイベントを受け取るのが順当だろう。
実装
まず ViewController に IBAction を追加する。
@interface RootViewController : UITableViewController { CGFloat cellHeight_; } // cell events - (IBAction)didTouchDoitButton:(id)sender; @end
続いて Xib へボタンを追加する。
ここで Xib の File's Owner に RootViewController を指定する。
そしてタップアクションのターゲットとして先ほど用意した IBAction へ接続する。
次にカスタムセルの生成コードに手を入れる。前回は -[UINib instantiateWithOwner:options:] の owner引数に nil を渡していた。これを self(=RootViewController)とする。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { CustomCell* cell = (CustomCell*)[tableView dequeueReusableCellWithIdentifier:CUSTOM_CELL_NIB]; if (cell == nil) { UINib* nib = [UINib nibWithNibName:CUSTOM_CELL_NIB bundle:nil]; // NSArray* array = [nib instantiateWithOwner:self options:nil]; // 前回 NSArray* array = [nib instantiateWithOwner:nil options:nil]; // 今回 : } :こうすることで Xib がインスタンス化された時に File's Owner が RootViewController のインスタンスとなり、ボタンがタップされた時に所定のメソッドが呼び出されるようになる。
最後にボタンタップ時の処理。
- (IBAction)didTouchDoitButton:(id)sender { id cell = sender; while (![cell isKindOfClass:[CustomCell class]]) { cell = [cell superview]; } NSIndexPath* indexPath = [self.tableView indexPathForCell:cell]; NSLog(@"%@", indexPath); }タップされたセルがどのモデルと紐づくかを知るには NSIndexPath が必要になるので -[UITableView indexPathForCell:] を使う。ただ、ボタンタップ時に呼び出されるこのメソッドの引数 sender には UIButton のインスタンスが入っているだけなので、ここからCustomCell のインスタンスを手に入れる必要がある。UIButton はカスタムセルの子ビュー(sub view) なので、逆に UIButton のビュー階層を上に辿っていって CustomCellクラスのインスタンスを探せば良い。
(2011-06-27追記)クラス検索は使わずに、タッチ位置から NSIndexPathを取得する方法が見つかった。そちらの方が汎用性があり実用的なので参照されたい。
Cocoaの日々: [iOS] UINib を使ったカスタム UITableViewCell の作り方(その3)ボタンの処理[改良版]
ソースコード
GitHub からどうぞ。
CustomCellSample at 2011-06-23 from xcatsan/iOS-Sample-Code - GitHub
Responses
Leave a Response