Reputation: 1815
What is the functional difference between instantiating a View Controller from the storyboard and creating a new instance of it? For example:
#import "SomeViewController.h"
...
SomeViewController *someViewController = [SomeViewController new];
versus
#import "SomeViewController.h"
...
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle: nil];
SomeViewController *someViewController = [storyboard instantiateViewControllerWithIdentifier:@"SomeViewController"];
In either case, is someViewController
effectively the same thing?
Upvotes: 44
Views: 33258
Reputation: 1028
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
}
}
Upvotes: 2
Reputation: 5453
The main difference is in how the subviews of your UIViewController
get instantiated.
In the second case, all the views you create in your storyboard will be automatically instantiated for you, and all the outlets and actions will be set up as you specified in the storyboard.
In the first, case, none of that happens; you just get the raw object. You'll need to allocate and instantiate all your subviews, lay them out using constraints or otherwise, and hook up all the outlets and actions yourself. Apple recommends doing this by overriding the loadView
method of UIViewController
.
Upvotes: 36
Reputation: 6031
In Swift you can do the same with,
var someVC = self.storyboard?.instantiateViewControllerWithIdentifier("SomeViewController") as! SomeViewController
You will need to give the Identifier in the Storyboard to the SomeViewController and tick the checkmark to Use Storyboard ID
Upvotes: 5
Reputation: 484
another thing to check for is if the viewcontroller that's throwing the error has a storyboardIdentifier, you can check the storyboard xib file.
the identifier was missing in my case, the error stopped when i added it
Upvotes: 0
Reputation: 1043
In case you don't want to instantiate a new VC using instantiateViewControllerWithIdentifier
but accessing the instance created by the storyboard from the AppDelegate:
@property (nonatomic, strong) myViewControllerClass*vC;
viewDidLoad
inside myViewControllerClass.m I access the shared instance of AppDelegate and feed the property with self: [AppDelegate sharedInstance].vC = self;
I had to use this solution in a complex storyboard and still can't get over the fact that I cannot find an easy way to access all (or at least the ones I need) objects in storyboard simply by addressing their identifiers.
Upvotes: 0
Reputation: 385670
In the second case, the view controller will load its view from the storyboard and you will be happy.
In the first case, it won't. Unless you've taken other steps (like overriding loadView
or viewDidLoad
or creating a xib named SomeViewController.xib
), you'll just get an empty white view and be sad.
Upvotes: 16
Reputation: 9687
It is not the same thing. In the storyboard you probably have some UI elements laid out. They might have constraints and properties setup through the storyboard. When you instantiate the viewcontroller via the storyboard, you are getting all the instructions for where those subviews are and what their properties are. If you just say [SomeViewController new]
you are not getting all the instructions that the storyboard has for the view controller.
A nice test will be to add a UIViewController to a storyboard and drag a red view onto it. Instantiate it using both methods and see what the differences are.
Upvotes: 3