So what I am trying to do is have a separate story board for all of the buttons in my app. EX for each of the buttons below I want it to take it to another storyboard with more then one view controller where I can then do separate screen switching for each number in the range specified below and at the end have a quick quiz. But if I use a single storyboard all the screens would be to clustered to work with. Because in my main menu I have three lesson options (Numbers, General communication, Travel) each of those have 10 sub-lessons and each sub-lesson has 10 signs then a quiz at the end.
So in my xcode project I have the storyboards:
Main
0-9
10-19
etc...
How can I switch from the Main storyboard to 0-9's storyboard.
Why don't you create one generic view and show what you want there? You can send the data(which quiz you have selected) through prepareForSeque function and then in the view controller prepare data you want to show. I think that every quiz have something in common, or you can group them as a true/false, MCMA and MCSA. Just a suggestion.
Just read your comment, can you relate to statements above?
To answer your question:
UIStoryboard *story = [UIStoryboard
storyboardWithName:#"storyboard_name"
bundle:nil];
CustomViewController *controller= [story instantiateInitialViewController];
After this you can push controller to navigation stack or something like this:
[self.navigationController pushViewController:controller animated:YES];
Ofcourse, if you want to do this via IB you can extend UIStoryboardSegue and do similar logic there.
Since I am a bit blind, I pasted objetive c code, not swift code.
Here you go:
let storyboard = UIStoryboard(name: "myStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("myVCID") as UIViewController
self.presentViewController(vc, animated: true, completion: nil)
Related
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Here is my storyboard image:
I want to create segue to viewController the red arrow is pointing to. This is a profile viewController. There will likely be three viewControllers linking to this viewController eventually. At present there will be two.
Now I can simply control drag show and create a segue. However this looks messy. My storyboard now has this diagonal line going underneath viewControllers.
Is this the expected way of doing this? Is it perfectly normal to have a line reaching from one up to another??
Thanks for your ans in advance.
You could actually just add the segue form the storyboard, and even with the diagonal line it would be ok. Just not for the eyes.
If you dont want your storyboard to get messy, you could instead put the profile controller in another part of the storyboard and then call it directly without using segues.
if let vc = UIStoryboard(name: "MyStoryboard", bundle: nil).instantiateViewControllerWithIdentifier(identifier: "viewControllerId") {
// Present or push the view controller using the proper function
}
To set the view controller identifier you can just click on it on the storyboard and fill the "Storyboard ID" field in the identity inspector.
In fact you can navigate your application to any of the viewCotroller anytime using segue or storyboard id. But there is a predefined rules here you must know about viewController's stack, whenever you load any viewController they appears in a stack which follows first in last out manner.
You can use segue to navigate your viewConteoller or storyboard ID.
Objective c:
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UIViewController *vc = [mainStoryboard instantiateViewControllerWithIdentifier:#"viewsId"];
// Note: use presentViewController or pushViewController one of them
[self presentViewController:vc animated:YES completion:nil];
[self.navigationController pushViewController:vc animated:YES];
In Swift:
let vc: UIViewController = (self.storyboard?.instantiateViewControllerWithIdentifier("viewsId"))!
// Note: use presentViewController or pushViewController one of them
self.presentViewController(vc, animated: true, completion: nil)
self.navigationController?.pushViewController(vc, animated: true)
I have a view controller reference to a storyboard of a given identifier. I'm adding a bunch of buttons to it, then trying to display it via a segue.
My problem is that when the segue fires, it creates a difference instance of the view controller with the same segue identifier, and thus it's blank.
What's the best practice to addSubView() to a storyboard, then getting that SAME storyboard object to display?
CLARIFICATION
Here's the flow I'm using:
Central VC -> Create SubVC using centralized Storyboard Object -> Adding SubViews to that SubVC in a factory class -> Queue Segue from SubVC back to the Central VC for segue using its identifier -> [it creates a NEW VC without my additions]
If you're using segues, then the Storyboard creates the destination viewController. If you want to customize the destination viewController, then you do that in prepareForSegue.
You can instantiate a view by code, and pushing in to you navigation controller, it's a clean approach and dont mess the Storyboard with unnecessary segues.
Just instantiate the next view (you must first give this view an StoryBoard ID), call it by code, and push it in the navigation controller.
Objective-C
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"storyBoard_Name" bundle:nil];
UIViewController* controller = [storyboard instantiateViewControllerWithIdentifier:#"ViewController_ID"];
[self.navigationController pushViewController:viewControllerName animated:YES];
Swift
let storyboard = UIStoryboard(name: "storyBoard_Name", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("ViewController_ID") as! UIViewController
self.presentViewController(vc, animated: true, completion: nil)
What is the best practice to switch between multiple views; change the rootViewController or use modal views?
Setting the rootviewController:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var vc : UIViewController = storyBoard.instantiateViewControllerWithIdentifier("viewTarget") as TargetViewController
var window :UIWindow = UIApplication.sharedApplication().keyWindow!
window.rootViewController = vc;
window.makeKeyAndVisible()
Changing the modal view:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initViewController: UIViewController = storyBoard.instantiateViewControllerWithIdentifier("viewTarget") as TargetViewController
self.presentViewController(initViewController,animated: false, nil)
I'm confused as to which to use when I need to present the user some other view.
p.s. In my case, I've an app starting with the login form as the rootViewController. After login, I think it's best to change the rootViewController but am I right?
My suggestion is instead of bothering lot about it you just got to override the rootviewController rest of the thing is taken care by your app.
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let initViewController: UIViewController = storyBoard.instantiateViewControllerWithIdentifier("viewTarget") as TargetViewController
self.window?.rootViewController? = initViewController
In this code we are just overriding rootview controller from AppDelegate.
The point of the "rootViewController" is to a a central pivot for all of your views.
See it as a the top-most link in series of chains. e.g. views on the left, can talk to views on the right can talk to views in the middle thanks to the "rootViewController". the "common link".. On top of that, it controls (or has the capability of controlling) how the hypothetical views on the left, right and middle are configured etc...
Fine, I worded it a bit trivially, but the (UINavigationController) is specifically for hierarchal content i.e. a UITabViewController is a great example..
I've just noticed a great post on here (Changing root view controller of a iOS Window) whilst finding a decent image to explain it decently.
Kudos to Matt on that post :) Hope this helps.
If not feel free to ask away :)
edit and for reference for others, here's something cheap and quick I slapped together that might get your head wrapped around storyboards :)
https://dl.dropboxusercontent.com/u/61211034/viewFun.zip
Cheers,
A
The application window's root view controller is the first view loaded into the window after the splash screen. Although it is possible to switch the window's view controller to change the view, consider using a UINavigationController and pushing additional view controller onto the view stack. This gives the user more flexibility, allowing the user to go back and forth between views.
I tried many answers here but none of them had the same exact scenario.
I'm trying to navigate to a UIViewController that's within a separated storyboard in a different bundle, so far I was able to navigate to it but am unable to return to the previous UIViewController. The method that invokes the external view controller (TabBarController) is implemented as follows:
+(void) launchExternalUI: (UIViewController *) previousViewController {
UIStoryboard* sb = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle: [self frameworkBundle]];
TabBarController *vc = (TabBarController*) [sb instantiateInitialViewController];
[previousViewController.navigationController pushViewController:vc animated:YES];
[vc release];
}
Now the method within TabBarController that should return to the previous view controller:
- (void) navigateToPreviousViewController: (UIGestureRecognizer *)gesture {
[self.navigationController popViewControllerAnimated:YES];
}
In TabBarController, if I print all the viewcontrollers within self.navigationController, all I see is the TabBarController, shouldn't I see the previous view controller that pushed this on launchExternalUI ? The [self.navigationController popViewControllerAnimated:YES]; has no effect at all. I'm a bit lost on this.
It's also important to notice that previousViewController is defined in a local storyboard and TabBarController is implemented in a different .framework, would that cause the issue?
Thanks in advance for all the help!
**Edit: The navigation flow I need is storyboard1:VC1->storyboard2:VC2->storyboard1:VC1, I can get storyboard1:VC1->storyboard2:VC2 part to work but not storyboard2:VC2->storyboard1:VC1
I often split projects up into various Storyboards, and have created a dynamic view controller that handles the task of loading the appropriate controller from a secondary storyboard, whilst maintaining the navigation tree.
I've created a sample project and uploaded to github as it's easier than explaining all the steps here. The key part to note is the User Defined Runtime Attributes for each of the DynamicStoryboardViewControllers in the Main.stoyboard. Note also that each of the secondary storyboards need the "is initial View Controller" checked for one of your viewControllers. Not included in the example is loading a specific scene from a storyboard. This is no more than adding the "sceneName" dynamic runtime attribute much in the same way as the storyboardName attribute is added.
it's a quick sample so a little rough, but you'll get the idea of how it all works. Feel free to ask questions if you get stuck.
Cheers!
EDIT:
It dawned on me that perhaps you don't have a navigationController in the view hierarchy (as i do in my sample). And in any event, seemingly, you won't have much control over where your tab bar is introduces. So without a navigationController the [self.navigationController popViewControllerAnimated:YES] won't work;
You should test for this and either call the popViewControllerAnimated as you do, or call dismissViewControllerAnimated ;
if(self.navigationController){
[self.navigationController popViewControllerAnimated:YES];
}else{
[self.presentingViewController dismissViewControllerAnimated:Yes completion:nil];
}
Hope this helps, if not, perhaps you can supply some sample code.
Create an unwind segue within your original view controller, and use segues instead of pushing/popping view controller views onto the view array.
To create an unwind segue you should create an unwind method in the ORIGINAL viewcontroller:
- (IBAction)unwindToOriginalViewControllerSegue:(UIStoryboardSegue*)sender {
; //TODO: anything special you need, reference via sender
}
Then, in your NEW viewcontroller, in the storyboard, drag from the controller icon to the Exit icon. Link that to the Unwind segue you named above.
UIViewController * YourViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"Storyboard Identifier"];
[self.navigationController pushViewController:YourViewController animated:TRUE];
I'm working on an app which uses Facebook integration, and the log in system works fine now. However, I can't seem to return to my initial view controller when the user clicks log out.
Here's an overview of my storyboard:
I would like to return to the start when the user clicks the blue button (on the top). What would I do to achieve that? As you can see I have multiple Navigation Controllers, and I only use Push-seguesto get there. However, I do use the SWRevealViewController, which you can see in the middle.
I've tried [self.navigationController popToRootViewControllerAnimated:YES]; which doesn't do anything.
Any advice? Anyone familiar with the SWRevealViewController and what it might have done to my Navigation stack? Any help will be appreciated!
Thanks.
Try this,
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"NameOfYourStoryBoard"
bundle:nil];
LoginViewController *add =
[storyboard instantiateViewControllerWithIdentifier:#"viewControllerIdentifier"];
[self presentViewController:add
animated:YES
completion:nil];
Write Below Method in root viewcontroller
- (IBAction)returnToDashboard:(UIStoryboardSegue *)segue;
Give segue connection to destination view controller like below
Give identifier to segue and assign method to that segue
use below method in destination view controller
[self performSegueWithIdentifier:#"pushtoDashboard" sender:self];
First of all, I don't think you need that many UINavigationControllers. Using only one in your application should be enough.
The reason popToRootViewController is not working in your case is because it will go to the first view controller withing a UINavigationController. You have nested many UINavigationControllers, thus when you click the blue button in the settings view controller it will go to the sidebar view controller (can't read it properly, the image is small).
You can do the following to get to the root view controller of your app:
UINavigationController *rootController =[(UINavigationController*)[(AppDelegate*)
[[UIApplication sharedApplication]delegate] window] rootViewController]];
Replace AppDelegate with however it's called in your app.
But my advice is to remove all intermediate UINavigationControllers. Then just doing popToRootViewController should do the trick.
Problem
You'd like to return from a view controller (source) to the start (a
destination view controller) when the user clicks the blue button (on the
top)
Recommendation
I recommend you take a quick look at the highly rated SO answer which demonstrates how to use the unwind segue (that's the little green exit box on your view controller in the storyboard). Unwind segues are the modern way of accomplishing your goal, but you can also call dismissViewController:animated from the source controller. You should also take a quick read of a very small Apple note (TN2298) on using the unwind segue.
Essentially you will want to add the following method to your destination view controller:
- (IBAction)unwindToMainMenu:(UIStoryboardSegue*)sender
{
}
Then use ctrl+drag and click from the blue button down to the green exit icon on the source view controller. This will popup a menu and you can select unwindToMainMenu from the list. You will need to give the new segue an identifier in the Identity Inspector (e.g. segueToMain).
Manual Unwind
The technical note above (TN2298) will also show you how you can create a manual unwind segues that may be called programmatically (similar to how one might say performSegueWithIdentifier...).
I was working on a very similar problem. I am using a storyboard with a navigation controller & implemented the highly recommended SWRevealViewController, with iOS 7 & Xcode 5.1. I tried unsuccessfully to implement some of the solutions mentions. Either the screen didn't change or I got blank table. I used a hybrid version of the programatic examples provided in SWRevealController & other answers here to get a working solution. I added this as apart of my login button action
UIStoryboard *storyBoard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
InboxTableViewController *viewController = [storyBoard instantiateViewControllerWithIdentifier:#"inbox"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:viewController];
[self.revealViewController pushFrontViewController:nav animated:YES];
I retrieved my storyboard & initiated the view controller I wanted from the storyboard & then added to a navigation controller. Finally I used the SWRevealViewController method to Push the view I desired to the front.
I'm using swift and what worked for me was this:
var loginVC: UIViewController? = self.storyboard?.instantiateViewControllerWithIdentifier("UILogin") as? UIViewController
self.presentViewController(loginVC!, animated: true, completion: nil)
When you have different storyboards simply "presenting" the required VC from the initial storyboard does the trick:
Swift 3
if let loginVC = UIStoryboard(name: "Login", bundle: nil).instantiateInitialViewController() {
present(loginVC, animated: true, completion: nil)
}
In some cases there might be leaking UITransitionView's. You might remove them right after the "presenting" code, but not before it and not in it's completion:
if let subviews = UIApplication.shared.keyWindow?.subviews,
let transitionViewClass = NSClassFromString("UITransitionView") {
for subview in subviews where subview.isKind(of: transitionViewClass) {
subview.removeFromSuperview()
}
}
<– This works as of Xcode 8.2.1 and iOS 10.2 but no guarantee if will work forever. Be careful with it.