Reputation: 5332
I am currently furiously digging through all the docs, and haven't quite found what I'm looking for. I suspect it is a real d'oh! answer.
I simply need to find the active storyboard in the main bundle, and want to know the best way to do this.
This is so that I can use the [UIStoryboard storyboardWithName:@"XXX" bundle:mainBundle]
to extract the running storyboard.
I know how to kludge it by switching on the idiom, but I feel that this is a...kludge.
What's a correct way of doing this?
Upvotes: 50
Views: 38979
Reputation: 1473
The better approach would be to get existing storyboard instance from window's rootViewController
if not available then create a new instance.
let storyboard = self.window?.rootViewController?.storyboard ?? UIStoryboard.init(name: "Main", bundle: nil)
Also using globally accessible helper functions like these can be a good idea provided that you pass the already active storyboard as parameter.
class Helper {
static func getLoginVC(storyboard: UIStoryboard) -> LoginVC {
return storyboard.instantiateViewController(withIdentifier: String(describing: LoginVC.self)) as! LoginVC
}
}
you can pass the active storyboard instance from a controller like this -
let loginVC = Helper.getLoginVC(storyboard: self.storyboard)
In case you are trying to access storyboard from appDelegate or sceneDelegate you can use -
let storyboard = self.window?.rootViewController?.storyboard ?? UIStoryboard.init(name: "Main", bundle: nil)
let loginVC = Helper.getLoginVC(storyboard: storyboard)
let navigationController = UINavigationController.init(rootViewController: loginVC)
self.window?.rootViewController = navigationController
self.window?.makeKeyAndVisible()
Upvotes: 1
Reputation: 1379
In case you want to get the active storyboard for a viewController, there's a storyboard property. This is how I solved it, instead of making a new instance:
LoginViewController *vc = [navController.storyboard instantiateViewControllerWithIdentifier:@"firstLaunch"];
[navController presentModalViewController:vc animated:YES];
In Swift you'd call:
let loginViewController = navigationController?.storyboard?.instantiateViewController(withIdentifier: "firstLaunch") as! LoginViewController
navigationController?.present(loginViewController, animated: true, completion: nil)
You could also be a lot safer by using guards against the navigation controller and the storyboard. I've used as!
so as to guarantee that you're getting a LoginController.
Upvotes: 41
Reputation: 22751
In Swift, you'd use the following syntax:
let storyboard = UIStoryboard(name: "Main", bundle: nil)
Note that passing nil
to bundle
will make the call refer to your main bundle automatically.
If you're in a view controller that you have on the Storyboard and want to instantiate the Storyboard from there directly, you can just do:
let storyboard: UIStoryboard? = self.storyboard // call this inside a VC that is on the Storyboard
Note that in the last case, self.storyboard
will return an optional Storyboard (Storyboard?
), so if you'd like to use it unwrap it like so:
if let storyboard = self.storyboard {
// access storyboard here
}
Upvotes: 7
Reputation: 317
I have just copy pasted the code form above updated question so that everyone can see it as an answer.
UIStoryboard *st = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:@"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
Upvotes: 0
Reputation: 5332
OK. As my comment above indicates, I found the answer to the (badly phrased question):
I wanted to be able to get the main (not active) storyboard, as I'm not using multiple storyboards per incarnation. I'm using the standard model of 1 storyboard for iPhone, and 1 for iPad. I just wanted the cleanest way to get the storyboard, so that I could use it to generate a view controller.
I found the answer in this post on Stack Overflow, and implemented it with the following code:
UIStoryboard *st = [UIStoryboard storyboardWithName:[[NSBundle mainBundle].infoDictionary objectForKey:@"UIMainStoryboardFile"] bundle:[NSBundle mainBundle]];
Upvotes: 27