iOS SDKによるiPhone/iPadアプリケーション開発入門

第3回View Controller概要

前回は、main関数からビューコントローラを使ってビューを作るまでのコードを説明しました。今回からはサンプルアプリケーションの作成を通して、iOSアプリケーション開発の様々な技法を学んでいきましょう。

まずは作成するサンプルアプリケーションのデザインを考えます。

作成するアプリケーションの概要

プロフェッショナルになるためには1万時間の訓練が必要であるという説があります。プロレベルまでいかなくても、一芸に秀でるためにはある程度まとまった時間が必要になります。この連載ではそんな練習を継続するモチベーションを助けるツールを開発します。機能一覧としては以下のような内容を想定しています。

  • 継続したい目標を登録する
  • 目標の一覧画面
  • 目標の経過時間登録画面
  • 日時設定によるリマインダ機能
  • 達成度をFacebookでシェアする

画面をデザインする

それでは個々の画面を簡単にデザインしてみます。

目標登録画面

目標のタイトルと、目標達成時間を入力するテキストフィールドを2つ用意します。

目標一覧画面

目標一覧画面では、登録した目標と、その達成時間が一覧できるようにします。また編集ボタンを押すと項目の削除ができるようにします。

経過登録画面

経過登録画面では、いつどれだけの時間取り組んだかを入力できるようにします。また、状況をシェアするためのボタンと、次にいつ取り組むかを設定するリマインダ設定も行えるようにします。

これらの画面デザインを以下に示します。今回はオンラインドローツールのCacooを使用しました。

図1 画面デザイン
図1 画面デザイン

画面イメージはこちらでも確認できます。

コンテナView Controllerを利用する

それでは画面イメージをもとに実装を進めていきましょう。まずはコンテナView Controllerの使用を検討します。

コンテナView Controllerとは、ほかのView Controllerを管理するView Controllerオブジェクトです。コンテナView Controllerには、階層的なデータの表示を管理するNavigation Controller、1つ以上の別々の操作モードに分割整理するTab Bar Controller、iPad用のPopover ControllerとSplit View Controllerがあります。Popoverはそれ自体はView Controllerではありませんが、他のView Controllerを管理します。Split View ControllerはiPadを横向きにしたときによく見られる画面で、2つのペインからなる情報を管理するコンテナView Controllerです。

今回は一覧画面と詳細画面とを階層構造にしたいため、Navigation Controllerを使用します。

それではコードを見て行きましょう。

アプリケーションデリゲートクラスのコードを以下のように変更します。

GihyoSample01AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];

  viewController = [[RootViewController alloc]init];
  navigationController = [[UINavigationController alloc]initWithRootViewController:viewController];  // -- (1)

  [window addSubview:navigationController.view];  // -- (2)
  [window makeKeyAndVisible];

  return YES;
}

(1)では、UINavigationControllerオブジェクトを作成しています。その後、initWithRootViewControllerメソッドによって前回作成したカスタムView ControllerであるRootViewControllerをナビゲーションの開始地点として指定しています。

(2)では、ウィンドウのサブビューとしてRootViewControllerのviewではなく、UINavigationControllerオブジェクトのviewを追加しています。

TableViewControllerを利用する

続いてRootViewControllerの実装を変更します。

一覧画面にはTable Viewを使用します。Table Viewを扱うにはTableViewControllerクラスを利用すると便利です。最初に作ったRootViewControllerの親クラスをUIViewControllerからUITableViewControllerクラスに変更します。

Table Viewにデータを表示するには、UITableViewDataSourceプロトコルのメソッドを実装する必要があります。

UITableViewDataSource

UITableViewDataSourceは、Table Viewに表示するデータを操作するために必要なメソッドを定義しています。最低限実装しなければいけないのは以下の2つのメソッドになります。

  • tableView:numberOfRowsInSection: Table Viewはセクションという単位で区切ることができます。このメソッドではセクション内に表示するアイテムの個数(行数)を返します。データを要求するUITableViewオブジェクトと、セクション番号を表すNSInteger値の二つの引数をとり、NSInteger型で行数を返すように実装します。
  • tableView:cellForRowAtIndexPath: テーブル内の各行(セル)をどのように描画するかを実装するためのメソッドです。データを要求するUITableViewオブジェクトと、セクションと何行目かを格納したNSIndexPathオブジェクトを引数に取り、UITableViewCellオブジェクトを返すように実装します。

それでは実装をみてみます。まずRootViewControllerの親クラスはUIViewControllerになっているため、これをUITableViewControllerに変更します。

RootViewController.h
@interface RootViewController : UITableViewController {
}

続いてRootViewController.mを変更します。まだデータを作成する部分ができていないので、確認用にダミーデータを表示するように実装しておきます。

RootViewController.m
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
  return 3;  // -- (1)
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

  static NSString *CellIdentifier = @"Cell";

  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];   // -- (2)
  if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
  }

  cell.textLabel.text = [NSString stringWithFormat:@"目標-%d", indexPath.row + 1]; // -- (3)

  return cell;
}

(1)はセクション内に表示する行数を返す部分です。とりあえず確認用なので3と固定にしておきます。実際のコードでは記録されているデータの個数を返すことになります。

(2)の行と次のif文が、テーブルビュー描画パフォーマンスを向上させるための典型的なコードです。このコードにより、一度作成したUITableViewCellオブジェクトを再利用することができ、描画速度が向上します。

(3)は実際にセルを描画するコードです。ひとまず確認用のコードを記述しています。

実行結果は次のようになります。

図2 実行結果
図2 実行結果

まとめ

今回はView Controllerのバリエーションとして、UINaviagtionControllerとUITableViewControllerを紹介しました。次回からは引き続き各種機能の実装を進めていきます。プロパティの宣言など記事中では省略している部分がありますので、コードの詳細については筆者のgithub上でご確認ください。

おすすめ記事

記事・ニュース一覧