[Xcode]Embed Inで追加したNavigationControllerの先にあるViewControllerへ値を渡す

Xcode.256x256-75
NavigationSample Main storyboard

Viewにナビゲーションバーを付けるとき、iOS 6まではEmbed Inを使わずにやってても見た目は問題なかったんだけど、iOS 7からは、ステータスバーがナビゲーションバーと一体化したので、マヌケな見た目になってしまう。

それを解決するためにはEmbed Inを使ってNavigationControllerを挟んでやればOK。遷移元の画面からは追加したNavigationControllerを呼び出してやればいい。ただし、ここで困ることが1つ。

Viewを1つ挟む形になるので、値を渡せなくなるのだ。

例としては上の画像のように、Aのテキストフィールドで入力した文字列をCのラベルに表示させる場合。

SPONSORED LINK

普通にやると”unrecognized selector sent to instance”エラー

これを解決するためには、画像Aビューで以下の手順を踏む必要がある。

  1. BのNavigation Controllerのインスタンス生成
  2. 生成したインスタンスのvisibleViewControllerプロパティを使ってCを取得
  3. Cのインスタンスを生成
  4. Cの.hファイルで宣言したプロパティに値を代入

陥りやすい点としては、Cのインスタンス生成ができていないと、値を代入しようとしても”unrecognized selector sent to instance”というエラーが出る所。どこに代入していいかわかんねえよ!ってエラー。

解決方法

解決方法としては以下のような形になると思う。直接見られる方法があったら理想なんだけどなぁ。。

SPONSORED LINK
// Segueを使用しない場合はIBActionで遷移させる
-(IBAction)willDisplayNavigationController:(id)sender
{
    // 元となるNavigationViewControllerのインスタンスを取得。
    // その先にある値を渡すためのViewController(ResultViewController)をそこから取得
    // 値を渡す。
    UINavigationController *nav = [self.storyboard instantiateViewControllerWithIdentifier:@"navigation"];
    ResultViewController *rvc = (ResultViewController *)nav.visibleViewController;
    rvc.strResult = self.input.text;
    
    // 画面遷移
    [self presentViewController:nav animated:YES completion:nil];
}

// Segueを使用する場合はdelegateメソッドで遷移(modalで繋ぐ)
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    // 遷移元画面で入力したテキストを遷移先画面のLabelに表示させる
    UINavigationController *nav = [segue destinationViewController];
    ResultViewController *rvc = (ResultViewController *)nav.visibleViewController;
    rvc.strResult = self.input.text;
}

※ C=ResultViewControllerとする。

visibleViewControllerってのが肝。最初はこれ知らなくてAppDelegateに変数宣言しててかなり可読性が悪くなってしまった。

githubにもサンプルをアップしておいたので良かったらどうぞ。

サンプル:hawk-a/send-parameter-sample

SPONSORED LINK
Xcode.256x256-75