Kikuchy's Second Memory

技術のこととか、技術以外のこととか、思ったことを書き留めています。

Xcode 5 + iOS 7 で、StoryBoard + TableView

最近進められていなかった mixi-inc/iOSTraining · GitHub を再開しました。

ところがXcode 5になってから mixi-inc/iOSTraining · GitHub にトライするのは初めてだった上、ドットインストールのiPhoneアプリ入門講座StoryBoard の便利さに気付いてしまった私は、どうしてもStoryBoardを使った開発をしたかったので、StoryBoardを使いながら mixi-inc/iOSTraining · GitHub をこなす方法を探してみました。


今回は 4.1 uitableviewについて4.2 uitableviewとnavigationcontroller に挑戦したので、これを xib を使わず StoryBoard だけでやってみたいと思います。


内容はオリジナルの教材と同じ順番で進めて行きます。

環境

手順

サンプルプロジェクトの作成

4.1 uitableviewについてサンプルプロジェクトの作成の内容を StoryBoard を使って行います。

普通に "Single View Application" を作成します。

f:id:kikuchy:20131103193730p:plain

プロジェクト名は "TableViewSampleWithStoryBoard" (好きな名前でOK)にしました。
iPad対応UIを作るのは面倒くさそうなので、Devicesは "iPhone" に変更しておきました。

f:id:kikuchy:20131103193742p:plain

あとは道なりに進んで行きます。

StoryBoard を使って TableView を用意する

プロジェクトが出来上がったらおもむろに "Main.storyboard" を開きます。

f:id:kikuchy:20131103193810p:plain

最初から ViewController が一つ置かれていますが、邪魔なので消します。
この ViewController の実体である、 "ViewController.m" と "ViewController.h" も消しておきます。

f:id:kikuchy:20131103193828p:plain

真っ白。
StoryBoard の右下から、 "TableViewController" を掴んで StoryBoard の何も無いところに放り込みます。

f:id:kikuchy:20131103193846p:plain

このままでは、この TableViewController はデフォルトの TableViewController のままなので、動作をカスタムしてやらないと面白くありません。
そのために、 TableViewController を継承した自作のクラスを用意し、「今StoryBoardに乗っているそのTableViewControllerはデフォルトのままじゃないんだ!」と宣言する必要があります。

ファイラーの "TableViewSampleWithStoryBoard" フォルダの中で右クリック、 "New File…" で新しいクラスを作ります。

f:id:kikuchy:20131103193905p:plain

"Objective-C class" で次へ。

f:id:kikuchy:20131103193916p:plain

Class は "TableViewController"、Subclass of は "UITableViewController" にしておきます。
これでデフォルトの "UITableViewController" を継承した自作のクラスが作れます。
今回はiPadに対応させないので "Targeted for iPad" のチェックは外し、
見た目もカスタムする訳ではないので "With XIB for user interface" のチェックも外します。

f:id:kikuchy:20131103193929p:plain

今作った TableViewController と StoryBoard のTableViewController を関連づけます。
StoryBoard に戻り、さっき作った TableViewController を選択。
Identity Inspector を開いて、Custom Class に "TableViewController" と入力します。

f:id:kikuchy:20131103193943p:plain

Objective-Cのprotocolは明示的な宣言が無くても実装できてしまいます。
が、C#からやってきた私としては、宣言無しでinterface実装、みたいなことは気持ち悪くてたまりません。
この後の作業を進めるために UITableViewDataSource と UITableViewDelegate を継承させておきます。

TableViewController.h を開いて、以下のように変更。

#import <UIKit/UIKit.h>

@interface TableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate>

@end

ここまでで、サンプルプロジェクトの作成の作業が終わりました。

tableviewのdataSource, delegateメソッドの追加

tableviewのdataSource, delegateメソッドの追加の内容です。
メソッドの解説などはオリジナルの教材の方をお読みください。

numberOfSectionsInTableView:tableView:cellForRowAtIndexPath:tableView:numberOfRowsInSection: を実装します。

numberOfSectionsInTableView: を編集するのは、このメソッドが0を返してしまうと何も表示されないからです。
編集するのが嫌であれば、元々書かれている numberOfSectionsInTableView: を丸々削除してください。

TableViewController.m を開いて当該メソッドを以下のように編集します。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;	// 0 -> 1 に変更
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return 10;	// 0 -> 10 に変更
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"%d", indexPath.row]; // 何番目のセルかを表示させました
    return cell;
}

事前準備 - NavigationControllerの追加

ここから 4.2 uitableviewとnavigationcontroller の内容に入ります。

オリジナルの教材ではコードで NavigationController を被せていますが、StoryBoard ではグラフィカルにできてしまいます。

Main.sotoryboard に戻り、TableViewController を選択します。
Xcodeのメニュー "Editor" -> "Embed in" -> "Navigation Controller" を選んで SotryBoard に NagigationController を埋め込みます。

f:id:kikuchy:20131103194016p:plain

StoryBoard はこんな風になっているはず。

f:id:kikuchy:20131103194027p:plain

didSelectRowAtIndexPath:animated:

オリジナルの教材ではコードの中で新しいViewControllerを生成して、そのViewへ画面遷移していました。
StoryBoardはそれもグラフィカルに(ry

右下から新しいViewControllerを追加します。

f:id:kikuchy:20131103194110p:plain

このViewControllerに遷移しましょう。
TableViewController から control キーを押しながら ViewController へドラッグ&ドロップします。
Segue の種類を選ぶメニューが出るので、ここでは "push" を選んでおきます。遷移の仕方はお好みでどうぞ。

f:id:kikuchy:20131103194133p:plain

また後で呼び出すのに必要なので、このSegueに名前を付けておきます。
Segueを選択して、 Attribute Inspector を開き Identifier に "selectRow" と入れておきます。

f:id:kikuchy:20131103194233p:plain

これだけではテーブルのセルを選択しても遷移してくれないので、コードに手を入れる必要があります。

TableViewController.m を開いて、didSelectRowAtIndexPath: メソッドを以下の内容で付け加えます。

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
	// 先ほど "selectRow" と名付けたSegueを実行します
    [self performSegueWithIdentifier:@"selectRow" sender:self];
}

シミュレーターで実行してみます。

テーブルに数字がズラリと並んでいます。

f:id:kikuchy:20131103194245p:plain

どれでも良いので適当なのを選択すると、

f:id:kikuchy:20131103194259p:plain

真っ白な画面に遷移しました。
ちゃんと StoryBoard で追加したViewControllerに遷移しましたね。

遷移後の画面に詳細データを表示する、とかそういう事をしたければ、ちゃんとしたDataSourceを用意する必要がありそうです。



ここまでで 4.2 uitableviewとnavigationcontroller の内容が終わりました。
お疲れ様でした!


StoryBoardを使うと何が良いかと言えば、画面遷移の様子が一目で見て分かるということでしょうか。
どのViewが一番最初に表示されて、どの画面からどの画面へ遷移するのか……
コードの中に埋もれがちな内容が一望できるというのは素晴らしいと思います。

Windows Store Application もそうですが、タブレットやモバイルのアプリケーションは画面遷移が多いので、画面間の繋がりを可視化して管理できるということには大きな利点があると思います。