ストーリーボード-AppDelegateのViewControllerを参照


122

次のシナリオを考えてみます。ストーリーボードベースのアプリがあります。ViewControllerオブジェクトをストーリーボードに追加し、このViewControllerのクラスファイルをプロジェクトに追加して、IB IDインスペクターで新しいクラスの名前を指定します。AppDelegateからプログラムでこのViewControllerを参照するにはどうすればよいですか?関連するクラスを使用して変数を作成し、それをIBOutletプロパティに変換しましたが、コードで新しいViewControllerを参照する方法が何もありません。接続をCtrlキーを押しながらドラッグしようとしても機能しません。 。

つまり、AppDelegate内で、次のようにベースのViewControllerにアクセスできます。

(MyViewController*) self.window.rootViewController

しかし、ストーリーボードに含まれている他のViewControllerはどうですか?


この回答を確認してください。迅速ですが、言語は似ています。
Borzh 2016年

回答:


165

ドキュメントをご覧ください-[UIStoryboard instantiateViewControllerWithIdentifier:]。これにより、IB属性インスペクターで設定した識別子を使用して、ストーリーボードからビューコントローラーをインスタンス化できます。

ここに画像の説明を入力してください

サンプルコードを追加するように編集:

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
                                                         bundle: nil];

MyViewController *controller = (MyViewController*)[mainStoryboard 
                    instantiateViewControllerWithIdentifier: @"<Controller ID>"];

こんにちはロビン、ありがとう。私はこのドキュメントを調べましたが、インスタンス化と初期化の単語が混ざっています...これにより、そこに到達します(指示に従った後:)(返信のコード形式の欠如をくそった...)UIStoryboard * mainStoryboard = [UIStoryboard storyboardWithName:@ 「MainStoryboard」バンドル:nil]; MyViewController * thisController =(MyViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:@ "myvc"];
Matthias D

これを見ている人のために、あなたのサンプルコードをフォーマット付きの回答に追加しました。
Robin Summerhill

24
ユニバーサルアプリを作成している場合は、必ずMainStoryboard_iPhone / MainStoryboard_iPadを使用してください。そうしないと、クラッシュします。
roocell 2011

16
デリゲート内から、次のようにinfo.plistによってロードされたストーリーボードインスタンスにアクセスできます。[[[self window] rootViewController] storyboard] ドキュメントによると、これは「ビューコントローラが発生したストーリーボード」を返します。(ストーリーボードからのものでない場合はnil)。そのUIStoryboard *から、@ RobinSummerhillが言及したインスタンス化呼び出しを使用できます。ストーリーボードは必要に応じてviewControllers(scenes)の新しいインスタンスをインスタンス化し、以前に表示されたインスタンスを再利用しないことに注意してください。
Tad Bumcrot、2012

6
OPは、現在実行中のvcで取得する方法を知りたいと考えています。ロードする方法ではありません。まさに彼が説明するように、あなたはかつてこのself.window.rootViewControllerを言うことができましたが、今はそれ以上はできません。
Fattie 2014年

41

XCode5 を使用する場合は、別の方法で行う必要があります。

  • あなたの選択UIViewControllerでをUIStoryboard
  • 行くIdentity Inspector右上のペインに
  • チェックUse Storyboard IDボックスをチェックします
  • Storyboard IDフィールドに一意のIDを書き込みます

次に、コードを記述します。

// Override point for customization after application launch.

if (<your implementation>) {
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" 
                                                             bundle: nil];
    YourViewController *yourController = (YourViewController *)[mainStoryboard 
      instantiateViewControllerWithIdentifier:@"YourViewControllerID"];
    self.window.rootViewController = yourController;
}

return YES;

4
私の知る限り、試すことができた限り、これが更新された答えです。
gnclmorais 2013年

ストーリーボードの名前は、拡張子なしのファイル名です。そのため、プロジェクトをこのように設定した場合は、「Main_iPhone」または「Main_iPad」になる可能性があります。
ブライアンホワイト

次に、ログイン後に元のrootViewControllerに戻る方法を教えてください。少なくともiOS 7とXcode 5.0.2に関する私の知識では、ルートビューコントローラーを元に戻すとすぐにアニメーションなしでビューの階層が切り替わります。UXチームは少ないコストでプログラマーを殺害しました。
lol

Swiftを使用してどうすればよいですか?
Leo Dabus 2014年

8

一般に、システムはストーリーボードを使用してビューコントローラーのインスタンス化を処理する必要があります。self.window.rootViewControllerビューコントローラーを初期化するのではなく、への参照を取得して、ビューコントローラー階層をトラバースします。

したがって、あなたrootViewControllerがUINavigationControllerであり、そのトップビューコントローラーに何かを送信したい場合は、AppDelegateで次のように実行しますdidFinishLaunchingWithOptions

UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
MyViewController *myVC = (MyViewController *)nav.topViewController;
myVC.data = self.data;

Swiftでは非常に似ています:

let nav = self.window.rootViewController as! UINavigationController;
let myVC = nav.topViewController as! MyViewController
myVc.data = self.data

ストーリーボードが読み込まれる通常の方法をバイパスして自分でストーリーボード全体を読み込む場合を除き、アプリのデリゲートからストーリーボードIDを使用してビューコントローラーを初期化しないでください。AppDelegateからシーンを初期化する必要がある場合は、おそらく何かがおかしいでしょう。なんらかの理由で、スタックを介してビューコントローラーにデータを送信したい場合、つまり、AppDelegateがビューコントローラースタックに到達してデータを設定してはいけません。それはそのビジネスではありません。rootViewControllerがビジネスです。rootViewControllerが自身の子を処理するようにします!したがって、info.plistファイル内の参照を削除することにより、システムによる通常のストーリーボードの読み込みプロセスをバイパスする場合は、多くの場合、次を使用してrootViewControllerをインスタンス化します。instantiateViewControllerWithIdentifier:、UINavigationControllerのようなコンテナの場合は、そのルート。回避したいのは、ストーリーボードによってすでにインスタンス化されているView Controllerをインスタンス化することです。これは私がよく目にする問題です。要するに、私は受け入れられた答えに同意しません。それ以外の場合は2つのストーリーボードをロードするため、ポスターがinfo.plistからストーリーボードのロードを削除することを意味しない限り、これは正しくありません。これは意味がありません。システムはルートシーンを初期化してウィンドウに割り当てたので、メモリリークではない可能性がありますが、その後、インスタンス化して再度割り当てました。あなたのアプリはかなり悪いスタートを切っています!


0
    UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
    self.window.rootViewController = [storyboard instantiateInitialViewController];
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.