UITableViewの行を選択した時の処理

2010/06/23

--2010/08/20追記 UITableViewを使った階層データの取り扱いはこのサイトが非常にわかりやすいです。

参考サイト

<a href="http://ameblo.jp/xcc/theme-10017889214.html target="_blank">【iPhoneアプリ開発ドリル】テーブルとナビゲーションを理解する

始めたばかりの頃の記事なので、以下の内容はあまり参考にならないかも・・・ いずれ自分なりにまとめてたいと思います。

UITableViewでNSDictionaryのデータをセクション表示した後、行を選択した時のデータ取得方法

外部ファイルに読み込まれるデータ定義

まずUITableViewに表示するデータを定義します。
@property (nonatomic, retain) NSDictionary *allNames;
@property (nonatomic, retain) NSMutableDictionary *names;
@property (nonatomic, retain) NSMutableArray *keys;
データの実装に関しては省略します。

行を選択した時の処理

-(void)tableView:(UITableView *)tableView
 didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSInteger row = [indexPath row];
    NSInteger currentSection = indexPath.section;
    NSString *key = [keys objectAtIndex:currentSection];
    NSArray *nameSection = [names objectForKey:key];
    NSString *currentName = [nameSection objectAtIndex:row];

NSString *message = [[NSString alloc] 
                     initWithFormat:@"%@", currentName];
UIAlertView *alert = [[UIAlertView alloc]
                      initWithTitle:@"Select Player"
                      message:message 
                      delegate:nil
                      cancelButtonTitle:@"OK" 
                      otherButtonTitles:nil
                      ];
[alert show];
[message release];
[alert release];
[key release];

}

UITableView.hのソースを見ると

@interface NSIndexPath (UITableView)
+ (NSIndexPath *)indexPathForRow:(NSUInteger)row inSection:(NSUInteger)section;
@property(nonatomic,readonly) NSUInteger section;
@property(nonatomic,readonly) NSUInteger row;
@end
NSIndexPathのインターフェイスにsectionが実装されています。 なのでドットシンタックスでアクセスするんですね --2010/07/22追記 大嘘・・・

メッセージ式で[indexPath section]と書いても同じ事です

しかしdidSelectRowAtIndexPathで選択オブジェクトを返してくれればいいと思うのは、 ActionScript系脳なのかな?w これがベストプラクティスなのかどうかはわからないけど・・・ --2010/07/22追記 行をクリックしたらというイベント系のメソッドなのでその方が都合が良い。 indexPathを使ってオブジェクトを自由に取得できるし。 -- 

話はそれますが、メッセージでネストしてやると以下のコードになります。

-(void)tableView:(UITableView *)tableView
 didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    UIAlertView *alert = [[UIAlertView alloc]
                          initWithTitle:@"Select Player"
                          message:[[NSString alloc] initWithFormat:@"%@",
                                   [[names objectForKey:
                                     [keys objectAtIndex:indexPath.section]] 
                                    objectAtIndex:[indexPath row]]
                                   ] 
                          delegate:nil
                          cancelButtonTitle:@"OK" 
                          otherButtonTitles:nil
                          ];
    [alert show];
    [alert release];
}
リファクタリングするとこうも書けます!って、あぁ、これはわかりにくい(爆) releaseとか面倒でも、わかりやすさからやっぱり僕は前者を選ぶかな?

--2010/07/22追記 init系のメソッドは、返されるオブジェクトを考慮してネストする事が推奨されている模様なので、initWithFormat等は暗黙の了解でネストしている。 結局はメモリ管理をどうするかによって、書き方が異なりそう。

まだ十分に把握できてないけど、この辺りはパフォーマンスチューニングとして頭の片隅においておいた方が良いかも。