これからiPhoneアプリの開発に関わることになったので、コソコソと勉強している今日このごろですが、Objective-Cはコードが読みづらいですね。私のブログといい勝負です。
そんな駆け出しの私ですが、コントローラ間のデータの受け渡しにかなり苦戦したので一度自分の知識と記憶をまとめるために記事にしておきます。
まぁこんな情報を垂れ流しているサイトはごまんとある訳ですから、分かりにくければ他のサイトも合わせて調べてみて下さい。
ちなみに開発環境はXcode5.0.2です。
Single View ApplicationでViewControllerを追加するところからのざっくりした手順は以下のとおりです。
説明の都合上、アプリを起動した時に表示されるコントローラをVC1、VC1とセグエで繋いでボタンを押すと遷移するコントローラをVC2として記載します。
VC1のクラスファイルが[ViewController.h]、[ViewController.m]です。
VC2のクラスファイルが[SecondViewController.h]、[SecondViewController.m]とします。
Xcodeのメニューの[File]→[New]→[File]と選んで、[Objective-C Class]を選択します。
クラス名は何でもいいですが、今回は「SecondViewController」とします。サブクラスはUIViewControllerで、チェックボックスはチェックせずそのままです。
ファイルの設置場所も変更せずそのまま行きました。ボリュームのあるアプリを作るときはフォルダ分けしておくと楽になるんでしょうか。
ここまで行くと左のプロジェクトナビゲーターにファイルが追加されているのが分かります。
ナビゲーターからMain.storyboardを選ぶと、メインのViewControllerが表示されます。
左のユーティリティペインの下段にあるオブジェクトライブラリから[View Controller]を選んでストーリーボードにドラッグします。
その後、追加したViewControllerを選択してユーティリティペインの上段を[Identity inspector](左から3つ目)に切り替えると、[Custom Class]という項目があるので、先程追加したSecondViewControllerを選びます。
ストーリーボードでオブジェクトライブラリからボタンを選んでVC1上にドラッグします。
その後、ドラッグしたボタンをcontrolキーを押しながらドラッグすると、水色の矢印が出てくるのでVC2まで引っ張ってきます。
VC2上にカーソルを合わせると、VC2の輪郭が水色になるので、その状態でドラッグを解除するとセグエのタイプを選べるので、とりあえず[modal]を選んでおきます。
今度は逆にVC2にボタンを配置します。
ここで先程と同じようにボタンを選んでセグエで繋ぎたいところですが、それをするとメモリ管理上よくないようなので、VC2からVC1に移動するのではなく、VC2からVC1に戻るというニュアンスの設定をします。
これは先程のようにマウスでちょいちょいとできないので、コードを書くことにします。
コードはVC1の方に書きますので、[ViewController.h]を開き、以下のコードを追記します。
場所は@implementation ViewControllerから@endの間ならどこでもいいようですので、一番最後に追記しておきます。
コードが書けたら、ストーリーボードに戻ります。
トリガーになるボタンが必要なので、ボタンをVC2上に配置します。
配置したボタンをcontrolキーを押しながらドラッグして、コントローラの下にある黄、赤、緑のアイコンの緑のアイコンにドラッグします。
すると、[Action Segue]というメニューが表示され、そこに先ほど追加したgoBackというメソッドが表示されていますので、これを選択します。
これでこのボタンを押すと、VC1に戻るという処理が実装出来ました。
ここまでの処理は、ドットインストールで3分くらいでまとめられているので、そちらを参考にしてもらうとよく分かると思います。 → #06 セグエを使ってみよう #07 もとの画面に戻ってみよう
VC1からVC2にデータを渡すためには、VC2に外部からデータの読み書きができる変数を作っておく必要があります。
まずはVC1に変数を作ってみます。
この変数はヘッダファイル(.h)で宣言します。
次に、メソッドファイル(.m)に受け取ったデータを処理するコードを書きます。
SecondViewController.mに移動すると、@implementation ViewControllerの部分に三角形の警告マークが出ます。
これは何かというと、変数data1を利用するために必要なおまじないが足りていないという事です。
この期に及んでおまじないとか言うなという感じですが、実はこの部分について説明できる知識が今のところありません。なので、ざっくりした事しか言えないのです。
とりあえずこの場を収めるためには、@implementationの行の後ろに以下のようにコードを追加します。
これでVC2で変数data1が使えるようになります。
処理をするタイミングによって、どのメソッドの中に書けばいいのかが色々ある訳ですが、セグエを使った画面遷移という事なので、遷移するタイミングに渡すことにします。
処理を書いていく前に、2つほどしておくことがあるので先にやってしまいます。
まず、セグエを特定できるように名前を付けておきます。
セグエで繋がれた箇所が1箇所のような場合には不都合は起きませんが、複数の画面をセグエで繋いでいく場合、どのセグエの場合にどの処理をするか処理を分ける必要があります。
というのも、セグエで遷移する処理に入った場合のメソッドは1つしかありません。それぞれのセグエに対してメソッドを割り当てるわけではないのでメソッド内でセグエが特定できるように、セグエに名前をつけるわけです。
ここでは、「myFirstSegue」としておきます。
ストーリーボードでVC1とVC2が繋がれている矢印をクリックして、ユーティリティペインの上段をAttributes Inspectorに切り替えると、[Identifier]という項目があるので、適当に名前をつけます。この名前は重複してはいけないようです(当然か)。
続いて、[ViewController.m]で[SecondViewController.h]をインポートします。
[SecondViewController.h]をインポートする事によって、SecondViewControllerのクラス定義が分かるので、ViewController.mから扱えるようになる訳です。
ちなみに[SecondViewController.h]をインポートしないまま次に進むとコード補完されないので「あれおかしいな」と思ってください。
いっそコード補完してコードを書くのが楽になるからと覚えてもいいんじゃないでしょうか(なげやり)。
記述する場所は、先頭の方にある「#import "ViewController.h"」の次の行あたりに書きます。
それでは、改めてデータを渡す部分の実装をしていきます。この処理は[ViewController.m]に記述していきます。
NSLogを使ってさくっと確認してみましょう。
今回はviewDidLoadというメソッドの中でdata1の内容を確認してみます。
viewDidLoadメソッドは、クラスのロードが完了した時に呼び出されるメソッドみたいです。
SecondViewController.mにNSLogを追加します。
以上です。
うまくいけば、xcodeのログにtestと表示されているはずです。
iOSのクラス間のデータ受け渡しには幾つかパターンがあるので、引き続き時間を見つけてまとめたいと思います。
そんな駆け出しの私ですが、コントローラ間のデータの受け渡しにかなり苦戦したので一度自分の知識と記憶をまとめるために記事にしておきます。
まぁこんな情報を垂れ流しているサイトはごまんとある訳ですから、分かりにくければ他のサイトも合わせて調べてみて下さい。
ちなみに開発環境はXcode5.0.2です。
Single View ApplicationでViewControllerを追加するところからのざっくりした手順は以下のとおりです。
説明の都合上、アプリを起動した時に表示されるコントローラをVC1、VC1とセグエで繋いでボタンを押すと遷移するコントローラをVC2として記載します。
VC1のクラスファイルが[ViewController.h]、[ViewController.m]です。
VC2のクラスファイルが[SecondViewController.h]、[SecondViewController.m]とします。
- VC2用のViewControllerを作成する
- ストーリーボードでViewControllerを追加してクラスを設定する
- セグエで繋ぐ
- VC1にVC2から戻る際の関数を追加して設定する
- VC2にデータ受取り用の変数を作成する
- VC1からVC2へデータを渡す処理を書く
- VC2でデータの受け渡しができているか確認する
VC2用のViewControllerを作成する
まずはVC2用のコントローラクラスを作成します。Xcodeのメニューの[File]→[New]→[File]と選んで、[Objective-C Class]を選択します。
クラス名は何でもいいですが、今回は「SecondViewController」とします。サブクラスはUIViewControllerで、チェックボックスはチェックせずそのままです。
ファイルの設置場所も変更せずそのまま行きました。ボリュームのあるアプリを作るときはフォルダ分けしておくと楽になるんでしょうか。
ここまで行くと左のプロジェクトナビゲーターにファイルが追加されているのが分かります。
ストーリーボードでViewControllerを追加してクラスを設定する
次はストーリーボードで設定をしていきます。ナビゲーターからMain.storyboardを選ぶと、メインのViewControllerが表示されます。
左のユーティリティペインの下段にあるオブジェクトライブラリから[View Controller]を選んでストーリーボードにドラッグします。
その後、追加したViewControllerを選択してユーティリティペインの上段を[Identity inspector](左から3つ目)に切り替えると、[Custom Class]という項目があるので、先程追加したSecondViewControllerを選びます。
セグエで繋ぐ
セグエで繋ぐには、トリガーになるオブジェクトが必要なので、ボタンをVC1に追加します。ストーリーボードでオブジェクトライブラリからボタンを選んでVC1上にドラッグします。
その後、ドラッグしたボタンをcontrolキーを押しながらドラッグすると、水色の矢印が出てくるのでVC2まで引っ張ってきます。
VC2上にカーソルを合わせると、VC2の輪郭が水色になるので、その状態でドラッグを解除するとセグエのタイプを選べるので、とりあえず[modal]を選んでおきます。
VC1にVC2から戻る際のメソッドを追加して設定する
VC1からVC2に遷移する設定は先程できましたが、戻ってくる処理が未実装なので、追加しておきます。今度は逆にVC2にボタンを配置します。
ここで先程と同じようにボタンを選んでセグエで繋ぎたいところですが、それをするとメモリ管理上よくないようなので、VC2からVC1に移動するのではなく、VC2からVC1に戻るというニュアンスの設定をします。
これは先程のようにマウスでちょいちょいとできないので、コードを書くことにします。
コードはVC1の方に書きますので、[ViewController.h]を開き、以下のコードを追記します。
場所は@implementation ViewControllerから@endの間ならどこでもいいようですので、一番最後に追記しておきます。
@implementation ViewController //この辺には元々あるコードが書いてあるので触らない - (IBAction)goBack:(UIStoryboardSegue *)sender{} @end
コードが書けたら、ストーリーボードに戻ります。
トリガーになるボタンが必要なので、ボタンをVC2上に配置します。
配置したボタンをcontrolキーを押しながらドラッグして、コントローラの下にある黄、赤、緑のアイコンの緑のアイコンにドラッグします。
すると、[Action Segue]というメニューが表示され、そこに先ほど追加したgoBackというメソッドが表示されていますので、これを選択します。
これでこのボタンを押すと、VC1に戻るという処理が実装出来ました。
ここまでの処理は、ドットインストールで3分くらいでまとめられているので、そちらを参考にしてもらうとよく分かると思います。 → #06 セグエを使ってみよう #07 もとの画面に戻ってみよう
VC2にデータ受取り用の変数を作成する
ここまではマウスを使った簡単な設定だけでしたが、ここからはオブジェクト指向に基づいたコードを書いていきます。VC1からVC2にデータを渡すためには、VC2に外部からデータの読み書きができる変数を作っておく必要があります。
まずはVC1に変数を作ってみます。
この変数はヘッダファイル(.h)で宣言します。
@interface SecondViewController:UIViewController { NSString *data1; } @property NSString *data1; @end
次に、メソッドファイル(.m)に受け取ったデータを処理するコードを書きます。
SecondViewController.mに移動すると、@implementation ViewControllerの部分に三角形の警告マークが出ます。
これは何かというと、変数data1を利用するために必要なおまじないが足りていないという事です。
この期に及んでおまじないとか言うなという感じですが、実はこの部分について説明できる知識が今のところありません。なので、ざっくりした事しか言えないのです。
とりあえずこの場を収めるためには、@implementationの行の後ろに以下のようにコードを追加します。
@implementation SecondViewController @synthesize data1;
これでVC2で変数data1が使えるようになります。
VC1からVC2へデータを渡す処理を書く
データの受取り口を作ったということで、いよいよVC1からVC2へデータを渡す部分の実装に入ります。処理をするタイミングによって、どのメソッドの中に書けばいいのかが色々ある訳ですが、セグエを使った画面遷移という事なので、遷移するタイミングに渡すことにします。
処理を書いていく前に、2つほどしておくことがあるので先にやってしまいます。
まず、セグエを特定できるように名前を付けておきます。
セグエで繋がれた箇所が1箇所のような場合には不都合は起きませんが、複数の画面をセグエで繋いでいく場合、どのセグエの場合にどの処理をするか処理を分ける必要があります。
というのも、セグエで遷移する処理に入った場合のメソッドは1つしかありません。それぞれのセグエに対してメソッドを割り当てるわけではないのでメソッド内でセグエが特定できるように、セグエに名前をつけるわけです。
ここでは、「myFirstSegue」としておきます。
ストーリーボードでVC1とVC2が繋がれている矢印をクリックして、ユーティリティペインの上段をAttributes Inspectorに切り替えると、[Identifier]という項目があるので、適当に名前をつけます。この名前は重複してはいけないようです(当然か)。
続いて、[ViewController.m]で[SecondViewController.h]をインポートします。
[SecondViewController.h]をインポートする事によって、SecondViewControllerのクラス定義が分かるので、ViewController.mから扱えるようになる訳です。
ちなみに[SecondViewController.h]をインポートしないまま次に進むとコード補完されないので「あれおかしいな」と思ってください。
いっそコード補完してコードを書くのが楽になるからと覚えてもいいんじゃないでしょうか(なげやり)。
記述する場所は、先頭の方にある「#import "ViewController.h"」の次の行あたりに書きます。
#import "ViewController.h" #import "SecondViewController.h" @interface ViewController()
それでは、改めてデータを渡す部分の実装をしていきます。この処理は[ViewController.m]に記述していきます。
@implementation ViewController // 色々な処理 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{ if ([[segue identifier] isEqualToString:@"myFirstSegue"]){ ViewController2 *VC2 = [segue destinationViewController]; VC2.data1 = @"test"; } } @end
VC2でデータの受け渡しができているか確認する
ここまで間違いなくコードができていれば、VC2の変数data1には、"test"という文字列が入っているはずです。NSLogを使ってさくっと確認してみましょう。
今回はviewDidLoadというメソッドの中でdata1の内容を確認してみます。
viewDidLoadメソッドは、クラスのロードが完了した時に呼び出されるメソッドみたいです。
SecondViewController.mにNSLogを追加します。
@implementation SecondViewController // 色々な処理 - (void)viewDidLoad{ [super viewDidLoad]; // 触らない NSLog(@"[%@]", data1); // 追記する } @end
以上です。
うまくいけば、xcodeのログにtestと表示されているはずです。
iOSのクラス間のデータ受け渡しには幾つかパターンがあるので、引き続き時間を見つけてまとめたいと思います。
コメント
コメントを投稿