次のシナリオを検討してください。ストーリーボードベースのアプリを持っています。 ViewControllerオブジェクトをストーリーボードに追加し、このViewControllerのクラスファイルをプロジェクトに追加し、IB IDインスペクターで新しいクラスの名前を指定します。 AppDelegateからこのViewControllerをプログラムでどのように参照しますか?関連するクラスで変数を作成し、それをIBOutletプロパティに変更しましたが、コードで新しいViewControllerを参照できる方法がありません-接続をCtrlキーを押しながらドラッグしようとしても機能しません。
つまり、AppDelegate内で、次のようにベースViewControllerにアクセスできます。
(MyViewController*) self.window.rootViewController
しかし、ストーリーボードに含まれる他のViewControllerはどうですか?
-[UIStoryboard instantiateViewControllerWithIdentifier:]
の- ドキュメント をご覧ください。これにより、IB Attributes Inspectorで設定した識別子を使用して、ストーリーボードからView Controllerをインスタンス化できます。
サンプルコードを追加するために編集:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
bundle: nil];
MyViewController *controller = (MyViewController*)[mainStoryboard
instantiateViewControllerWithIdentifier: @"<Controller ID>"];
XCode
5を使用する場合は、別の方法で実行する必要があります。
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;
一般的に、システムはストーリーボードを使用してView Controllerのインスタンス化を処理する必要があります。必要なのは、ストーリーボードを適切に設定していれば、すでに正しく初期化されているはずのView Controllerを初期化するのではなく、self.window.rootViewController
への参照を取得してviewController階層をトラバースすることです。
したがって、あなたのrootViewController
がUINavigationControllerであり、そのトップビューコントローラーに何かを送信したい場合、AppDelegateのdidFinishLaunchingWithOptions
で次のようにします。
UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
MyViewController *myVC = (MyViewController *)nav.topViewController;
myVC.data = self.data;
Swiftのifは非常に似ています:
let nav = self.window.rootViewController as! UINavigationController;
let myVC = nav.topViewController as! MyViewController
myVc.data = self.data
ストーリーボードの通常のロード方法をバイパスして、ストーリーボード全体を自分でロードする場合を除き、アプリデリゲートからのストーリーボードIDを使用してView Controllerを初期化するべきではありません。 AppDelegateからシーンを初期化する必要がある場合、おそらく何か間違ったことをしている可能性があります。何らかの理由で、スタックを介してView Controllerにデータを送信したい場合、AppDelegateがView Controllerスタックに到達してデータを設定することはないはずです。それはビジネスではありません。それがビジネスであるのはrootViewControllerです。 rootViewControllerに独自の子を処理させます!したがって、info.plistファイル内の参照を削除することにより、システムによる通常のストーリーボードのロードプロセスをバイパスする場合、せいぜいinstantiateViewControllerWithIdentifier:
を使用してrootViewControllerをインスタンス化し、コンテナの場合はそのルート、 UINavigationControllerのように。避けたいのは、ストーリーボードによって既にインスタンス化されているView Controllerをインスタンス化することです。これはよく見かける問題です。要するに、私は受け入れられた答えに同意しません。ポスターがストーリーボードのロードをinfo.plistから削除することを意味しない限り、それは間違っています。システムがルートシーンを初期化してウィンドウに割り当てたため、おそらくメモリリークではありませんが、その後になって、再びインスタンス化して再度割り当てました。あなたのアプリはかなり悪いスタートを切っています!
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
self.window.rootViewController = [storyboard instantiateInitialViewController];