ストーリーボードからView Controllerをインスタンス化することと、その新しいインスタンスを作成することの機能的な違いは何ですか?例えば:
#import "SomeViewController.h"
...
SomeViewController *someViewController = [SomeViewController new];
versus
#import "SomeViewController.h"
...
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
SomeViewController *someViewController = [storyboard instantiateViewControllerWithIdentifier:@"SomeViewController"];
どちらの場合でも、someViewController
は事実上同じものですか?
主な違いは、UIViewController
のサブビューがインスタンス化される方法です。
2番目のケースでは、ストーリーボードで作成したすべてのビューが自動的にインスタンス化され、ストーリーボードで指定したとおりにすべてのアウトレットとアクションがセットアップされます。
最初のケースでは、それは起こりません。生のオブジェクトを取得するだけです。すべてのサブビューを割り当ててインスタンス化し、制約などを使用してレイアウトし、すべてのアウトレットとアクションを自分で接続する必要があります。 Apple推奨loadView
のUIViewController
メソッドをオーバーライドしてこれを実行します。
2番目のケースでは、View Controllerがストーリーボードからビューをロードし、満足します。
最初のケースでは、そうではありません。他の手順(loadView
またはviewDidLoad
のオーバーライド、またはSomeViewController.xib
という名前のxibの作成など)を行っていない限り、空の白いビューが表示され、悲しくなります。
Swiftで同じことができます、
var someVC = self.storyboard?.instantiateViewControllerWithIdentifier("SomeViewController") as! SomeViewController
ストーリーボードのIdentifierをSomeViewControllerに指定し、チェックマークをストーリーボードIDを使用にチェックする必要があります。
同じものではありません。ストーリーボードには、おそらくいくつかのUI要素がレイアウトされています。ストーリーボードを使用して、制約とプロパティを設定できます。ストーリーボードを介してViewControllerをインスタンス化すると、それらのサブビューがどこにあり、そのプロパティが何であるかについてのすべての指示が得られます。単に[SomeViewController new]
ストーリーボードがView Controllerに対して持っているすべての指示を取得していない。
素敵なテストは、UIViewControllerをストーリーボードに追加し、その上に赤いビューをドラッグすることです。両方の方法を使用してインスタンス化し、違いを確認します。
simple Swift 3 extension
fileprivate enum Storyboard : String {
case main = "Main"
}
fileprivate extension UIStoryboard {
static func loadFromMain(_ identifier: String) -> UIViewController {
return load(from: .main, identifier: identifier)
}
static func load(from storyboard: Storyboard, identifier: String) -> UIViewController {
let uiStoryboard = UIStoryboard(name: storyboard.rawValue, bundle: nil)
return uiStoryboard.instantiateViewController(withIdentifier: identifier)
}
}
// MARK: App View Controllers
extension UIStoryboard {
class func loadHomeViewController() -> HomeViewController {
return loadFromMain("HomeViewController") as! HomeViewController
}
}
新しいVCを使用してinstantiateViewControllerWithIdentifier
を使用して、AppDelegateからストーリーボードによって作成されたインスタンスにアクセスする場合:
@property (nonatomic, strong) myViewControllerClass*vC;
viewDidLoad
でAppDelegateの共有インスタンスにアクセスし、プロパティにself:を送ります:[AppDelegate sharedInstance].vC = self;
複雑なストーリーボードでこのソリューションを使用する必要がありましたが、簡単な方法でアクセスできないという事実を克服することはできませんすべて(または少なくとも必要なもの)識別子のアドレス指定。
もう1つ確認するのは、エラーをスローしているViewControllerにstoryboardIdentifierがある場合、ストーリーボードのxibファイルを確認できることです。
私の場合は識別子がありませんでしたが、追加するとエラーが停止しました