NewImage

よく見かけるようなUITableViewを使った”このアプリについて”といった画面を簡単に作れるようにしたいなーと思ったので、簡単に作ってみました。
ソースコードはGithubにおいてあります

実装した機能

  • datasourceは別のクラスで作ってセットできる
    • 選択した際の挙動についてもdatasourceにblockで書ける
  • Cell 背景とかを少しカスタマイズ
  • ライセンス表示用のWebViewがセット
  • 問い合わせ用にMFMailComposeViewControllerでメールを立ち上げる機能

簡単な解説を書いていくと、TableViewController(ソースではAboutAppTableViewController)にdatasourceやタップしたらといったものは書かないようにして、
外からインスタンス化した時などにdatasourceを渡せるような構造にしてみました。

サンプルなので、datasourceを渡す部分もAppDelegate.mにまとめて書いちゃってますが、この辺もそれ用のクラスを用意したほうがいいのかもしれない。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Section Names
    NSArray *sectionTitles = [NSArray arrayWithObjects:@"About App", @"Other", nil];

// make data for each section
    NSString *appNameString = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *) kCFBundleNameKey];
    NSString *versionString = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *) kCFBundleVersionKey];
    NSArray *section1;
    section1 = [NSArray arrayWithObjects:
                            [NSDictionary dictionaryWithObjectsAndKeys:
                                              @"App Name", kCellTextKey,
                                              appNameString, kCellDetailTextKey,
                                              nil],
                            [NSDictionary dictionaryWithObjectsAndKeys:
                                              @"Version", kCellTextKey,
                                              versionString, kCellDetailTextKey,
                                              nil],
                            nil];
    NSArray *section2;
    section2 = [NSArray arrayWithObjects:
                            [NSDictionary dictionaryWithObjectsAndKeys:
                                              @"License", kCellTextKey,
                                              Block_copy(^(NSIndexPath *indexPath) {
                                                  [self pushWebView];
                                              }), kDidSelectBlock,
                                              [NSNumber
                                                  numberWithInteger:UITableViewCellAccessoryDetailDisclosureButton],
                                              kCellAccessoryType,
                                              nil],
                            [NSDictionary dictionaryWithObjectsAndKeys:
                                              @"Question?", kCellTextKey,
                                              Block_copy(^{
                                                  [self showMailComposeView];
                                              }), kDidSelectBlock,
                                              @"mail", kCellAccessoryType,
                                              nil],
                            nil];
    NSArray *sections = [NSArray arrayWithObjects:section1, section2, nil];


    self.viewController = [[[AboutAppTableViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
    self.viewController.title = @"About";
    self.viewController.dataSource = sections;
    self.viewController.sectionTitles = sectionTitles;
    // Navigation Controller
    self.navigationController = [[[UINavigationController alloc]
                                                          initWithRootViewController:self.viewController] autorelease];
    // window
    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
    self.window.rootViewController = self.navigationController;
    [self.window makeKeyAndVisible];
    return YES;
}

という感じで、sectionやその中のcellについての情報を作ってself.viewController.dataSource = sections;で渡すような感じにしています。
TableViewを表示した後でも、同じようにdataSourceを渡してreloadDataをすればTableViewの内容が更新できます。

    self.viewController.dataSource = sections;
    self.viewController.sectionTitles = sectionTitles;
    // TableView更新
    [self.viewController.tableView reloadData];

それぞれ、SectionとそのSectionの中にNSDictionaryの配列を書いていく感じで、TableViewの内容を決めていけるようにしています。
NSDictionaryのkeyでいくつかの要素を指定できる感じです。

今の所指定できるようにしたのは次の要素です。

  • kCellTextKey
    • Cellの左部分のテキスト
  • kCellDetailTextKey
    • Cellの右部分のテキスト
  • kCellAccessoryType
    • CellのUITableViewCellAccessoryType
    • 数字はkeyに入れられないので、NSNumberでラップしたものを渡す。
    • @”mail” という文字列を指定することで、最初のスクリリーンショットみたいなメールアイコンが出るのも加えた
  • kDidSelectBlock 
    • 選択した際の挙動についてBlockで書く
    • 書かなかった場合は何もおきない

という感じです。

kDidSelectBlockでcellをdidSelectRowAtIndexPathした時の挙動をBlockで書けますが、渡すBlockはそのままだとスコープを抜けた時に破棄されてしまうのでBlock_copy()を使って、
ヒープへコピーしてから渡すようにしています。(あんまり自信ない)

こういう書き方で合ってるのかはよくわかりませんが、タップした時の処理もCellの表示内容と一緒にかけるととても楽です。
これを利用して、LicenseWebViewControllerで用意したライセンスについて書いたhtmlを表示する機能やメールについて動作を書いています。

UITableViewなものを改めて考えて書いてみると意外と勉強になる部分が多かった。
UITableViewの書き方は iOS開発におけるパターンによるオートマティズム に沿った感じの書き方をしています。

最近だと、UITableViewの使い方については以下の記事が面白そう。

TableViewについてだけで一冊本がでるぐらい

UITableViewはいろいろ使い道があって便利ですが、もっと楽に書きたいです。

Post Navigation