今回はUITableVIewの行をタップした時に別画面を呼び出す
部分を作ります。
行をタップした時にプログラム内部ではUITableViewDelegateで定義されている
tableView:didSelectRowAtIndexPath:メソッドが呼ばれます。
なので、このメソッド内に別画面を呼び出す処理を書いていきます。
学べること
- Interface Builderの基本的な使い方
- UITableViewの行選択時の動作
- navigation Controllerによる画面遷移
前提条件
- 【UITableView】UITableViewにリストを表示するのプロジェクトを使用
手順
- 新規画面のビュー作成
- 新規画面のコントローラ作成
- ビューとコントローラの関連づけ
- 親画面から新規画面の呼び出し
- ビルド
新規画面のビュー作成
行をタップした時に別画面を呼び出す処理を書こうにも呼び出す画面がなければ書きようがないので、
まずは画面を用意します。
iphoneアプリ開発ではMVCモデルと呼ばれるパターンが使われていますが、
画面はMVCのうちのV、ビューにあたります。
ビューはコードをゴリゴリ書いて作り上げることもできますが、
Interface Builderを使うと見た目を確認しながら感覚的に作ることが
できるので、こちらの方法で作成することにします。
nibファイルの作成
Interface Builderで作成するファイルはnibファイルと呼ばれますが、まずはこれから作ります。
Xcodeの左のツリーからResoucesを選択した状態で
右クリック→追加→新規ファイルとしてファイル追加ウィンドウを表示します。

新規ファイルとしてVIEW XIBを選択して、次へを押します。

ファイル名を入力します。ここではDetailView.xibとします。
次に完了を。

左のツリーのNIBファイルをクリックするとDetailView.xibが作成されているのが確認できます。
次に画面上部のファイルリストからDetailView.xibをダブルクリックして
Inteface Builderを起動します。
起動するとこんなウィンドウが出ます。

これがnibファイルの中身で、3つのオブジェクトが
含まれています。
もう一つviewという真っ白なウィンドウが表示されます。

これがiPhoneで表示される画面です。
ここにいろんなパーツを追加していきます。
パーツの追加はLibraryから行います。
Libraryはこんなウィンドウです。

Libraryの外観は左下の設定ボタンで
アイコンのみを表示など変更ができます。
Libraryが起動していない場合、
上部のメニュー→Tools→Libraryとして起動します。

あとはオブジェクト同士の接続や、表示設定をするための
Inspectorウィンドウがあります。

起動していない場合は、
メニュー→Tools→Inspectorとして起動します。

今回はこの空っぽのつまらない画面を
表示するのにとどめます。
一度にいろいろやりすぎると
どの操作がどの結果につながっているのかが
わかりにくくなるので。
新規画面のコントローラ作成
というわけで、次にビューに紐づくコントローラを作成します。
コントローラはモデルとビューとの橋渡し役です。
画面上での操作をコントローラが受けて
モデルへ処理をさせたり、別のビューを表示したり
するのがコントローラの役目です。
左のツリーClassesを選択して
右クリックから→新規→新規ファイル追加として
ファイル追加ウィンドウを表示します。

Cocoa Touch Classesの中からUIViewController subclassを選択して次へ。

ファイル名はDetailViewController.mとします。
このとき、同時に”DetailViewController.h”も作成にチェックを忘れずに。

以上でコントローラが作成されましたね。
次にこのコントローラとビューとを紐づけます。
ビューとコントローラの関連づけ
ビュー、コントローラ、それぞれの作成は済みましたがこれらは何の関連もまだ持っていません。
ビューを管理をするコントローラを紐付けます。
File’s Ownerとコントローラの紐付け
まずDetailView.xibウィンドウのFile’s Ownerオブジェクトを選択して
Inspectorウィンドウの一番右のタブIdentityを選択して
一番上のClass Identityプルダウンで先ほど作成したDetailViewControllerを
選択します。

これでDetailView.xibの所有者は
DetailViewControllerだという設定がされました。
ビューとFile’s Ownerの紐付け
次はビューとFile’s Ownerを関連づけます。File’s Ownerを右クリックすると
黒いウィンドウが表示されます。

このウィンドウ内のOutletsの中にviewという項目があるので、
その項目の右の○をドラッグして、viewウィンドウまで
引っ張ってドラッグをはなします。
するとこんな感じでview項目にドラッグ先のviewが紐づきます。

File’s Ownerとコントローラを紐付け、
File’s Ownerとビューを紐付けたので、
これでコントローラとビューの紐付けが完了しました。
新画面の準備はこれで全部完了です。
Interface Builder上でCommand+Sとして
内容を保存しておきましょう。
親画面から新規画面の呼び出し
編集するファイル
- RootViewController.m
いよいよ新画面の呼び出し処理を書きます。
冒頭でも説明した通り、UITableViewで選択行をタップすると
tableView:didSelectRowAtIndexPath:メソッドが呼ばれます。
ここに呼び出す処理を書きます。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailView" bundle:nil];
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
} |
まず先ほど作成したDetailViewControllerのインスタンスを作成します。
[DetailViewController alloc]
作成したインスタンスのinitWithNibName:bundleメソッドを使って初期化します。
initWithName:に指定する名前はビューの名前と同じにする必要があります。
ここではDetailView.xibを作成したので、名前にDetailViewを指定しています。
bundleはひとまずnilで問題ありません。
次に作成したコントローラのインスタンスをnavigationコントローラの
スタックに追加します。
navigationコントローラはスタックに積まれた一番上のコントローラを表示制御
に選択するので、プッシュされたコントローラに対応する画面が表示されます。
最後にプッシュされたDetailViewControllerのインスタンスは
navigationコントローラ内で参照カウンタが1つ増やされるので、
こちらで作成したインスタンスはreleaseして参照カウンタを1つ戻します。
javaやC#といったガベージコレクションをしてくれる
言語を使っていた僕にとってはこのreleaseで参照を解放してしまう
という理屈がはじめ理解できなくてハマりましたが、
最近やっとObjective-Cのメモリの管理方法を理解してきて
分かるようになりました。
参照カウンタ系の話はまた別で書きます。
これだけだと、RootViewController.mはDetailViewControllerという
クラスがどれなのか判断がつかないので、ファイルの頭で
以下のようにDetailViewController.hをimportしておきます。
#import "RootViewController.h" #import "HelloWorldAppDelegate.h" #import "DetailViewController.h" @implementation RootViewController |
以上でコーディングは終了です。
ビルド
それではビルドしてみましょう。起動画面はこれまで作成したリストが表示されています。

ここで行を選択すると下のような新しい画面が表示されます。

でもちょっと待ってください。
さっきは空っぽのビューを用意しただけなのに、
画面上部にナビゲーションバーが表示されていますね。
この部分はnavigationコントローラが作っています。
navigationControllerのスタックに新画面をプッシュしたので、
新画面は始めの画面の小画面だよとnavigationControllerが
認識していて、画面上部に自動的に親画面へ戻るボタンを
表示してくれているわけですね。
同時にいろいろやりすぎるとこのような基本的な
部分の処理がどこで行われているのかが
見えなくなってしまうので今回は
あえて何も表示しないビューを作成しました。
選択行から別画面を呼び出すは以上です。
ちなみにnavigationControllerの
pushViewController:animatedメソッドの
animatedにYESを渡しているので
いかにもiPhoneらしいみよ〜んという
アニメーションで新画面を表示していますが、
animated:NOとするとニヒルにシュッと新画面を
表示できます。
関連のあるアプリ
タグ: Interface Builder, iPachi, iphone, Navigation Controller, objecti, objective-c, UITableView, UIViewController, Xcode, アイコン, アプリ, チュートリアル, パチスロ, リスト, リリース, 動画, 収支, 画面遷移



10月 7th, 2009 at 2:46 AM
わかりやすい説明で大変参考になっています
自分なりに応用しようと思ったのですが、いかんせん初心者のため進めなくなりました。教えていただけると助かります
この記事用に別画面を呼び出し、さらにその画面から別の画面を呼び出したいのですが、どうしても2回目の移動ができません。
もしかすると仕様で一回のみになっているのかもと思っているのですが、簡単なやりかたを教えていただけると助かります
10月 11th, 2009 at 3:31 PM
>cessnaさん
仕様で2回目の移動ができないということはありません。何かしらの不具合があるのだと思います。
開発を始めたばかりだと一番多いのはメモリリーク関連の不具合でアプリがクラッシュしてしまうことだと思います。
以前メモリリークやデバッグ関連の記事をまとめたのでこのあたりを参考にしてみてください。
【iPhone】メモリ不足時のシミュレートとデバッグ | iphoneアプリで稼げるのか
10月 22nd, 2009 at 11:44 PM
こんにちは、コメントありがとうございます
ようやく解決しましたのでお礼に参りました
完全に誤解していたのですが、navigationControllerを新たに別のものを設定していたのでうまくいきませんでした。
メソッドで渡す様にしてやることで2回目の移動もできました。
もっとスマートなやり方もあるのかもしれませんが。
10月 31st, 2009 at 11:30 PM
>cessnaさん
navigationControllerは、initする時にrootControllerとして指定したものを初期表示のコントローラとして、スタックで管理してくれるものなので、コントローラをpushやpopすることで表示中の画面を制御できます。なので、2回目の遷移をしたい時は、初めに用意したnavigationControllerに対して、表示したいコントローラをpushすればいけます。
navigationControllerを別のものに変えてしまうと、別のスタックでコントローラが管理されてしまうので確かにうまくいかなそうです。