I have the mainstoryboard + viewcontroller
When I press a button on the mainstoryboard it will show another storyboard.
When I press a button in the new storyboard I want to call a function of the mainstoryboard.
How can I make this happen?
You can grab the storyboard and instantiate a viewController from it like this:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"yourStoryboardName" bundle:nil];
YourViewController *viewController = [storyboard instantiateViewControllerWithIdentifier:#"yourViewControllerIdentifier"];
But if you require a function that contains the context of the previous view controller, you should keep a reference to it and just call your methods directly from there. You can also use the presentingViewController property to access the view controller that started the modal presentation. Or if using a navigationController you can use the viewControllers property to access previous viewControllers in the stack.
The comment of Abizem gave me the right tag to search for.
'Protocols'.
I found a very good explanation here on stackoverflow.
Look there:
How to access a previous story board.
Just have a look at the answer of Matt Price. Very nice explanation!
Related
I have an app that uses a Navigation Controller with three View Controllers for step-by-step user setup. So the first View would be Step 1, second Step 2, and etc. And all this would be embedded in a Navigation Controller so the user would be able to go back and forth. However, once this setup is done and the user presses the 'Done' button, the app programmatically moves to another section of the storyboard which is supposed to be separate from the initial setup. I programmatically segue to this section with the following code:
let vc : AnyObject! = self.storyboard!.instantiateViewControllerWithIdentifier("welcomeViewController")
self.showViewController(vc as! UIViewController, sender: vc)
where "welcomeViewController" is the identifier for the post-setup ViewController. However, once this happens, the Navigation Controller Bar still appears on the top and you can still navigate back into the setup menu, which is not at all what I want. Here's what I mean:
The user shouldn't be able to access the initial setup after already setting up. My storyboard looks like this:
The left four boxes are for setup. The right three boxes is the 'Main Menu' I want to create.
As you can see, there's no arrow between the last setup Controller and the Tab Bar Controller because I performed that segue programmatically (as shown above). How do I get the Navigation Controller to stop affecting the rest of my View Controllers?
This happens because a segue under the hood makes use of the current UINavigationController, so it doesn't matter if you perform the segue programmatically or in the storyboards directly.
There a number of ways how to approach this. A very easy way to achieve it is to simply hide the back button in your WelcomeViewController using self.navigationItem.hidesBackButton = YES;.
However, this doesn't really solve your problem if you really want a separation between these view controllers and want to get rid of the UINavigationController that was responsible for your setup process. What I would actually recommend for that kind of situation is to use two different storyboards, one for your initial setup and one for the main part. Then you switch your UIWindow's rootViewController to a view controller from the other storyboard programmatically. This can be done in few lines of code and helps to separate your concerns and keep a better visual overview on your app's flow.
Let me know in the comments if you need further explanation :)
Switching storyboards can be achieved using the following code:
UIStoryboard *main = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UIViewController *welcomeViewController = [main instantiateViewControllerWithIdentifier:#"WelcomeViewController"];
UIWindow *mainApplicationWindow = [[[UIApplication sharedApplication] delegate] window];
mainApplicationWindow.rootViewController = welcomeViewController;
But if you want to instantiate the whole UITabBarController you use in you r main interface, you'll have to give it an ID (e.g. MainTabBarController) in storyboards so that you can instantiate it using instantiateViewControllerWithIdentifier:. So then, instead of instantiating your WelcomeViewController, you'll go:
UIStoryboard *main = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
UITabBarController *mainTabBarController = [main instantiateViewControllerWithIdentifier:#"MainTabBarController"];
UIWindow *mainApplicationWindow = [[[UIApplication sharedApplication] delegate] window];
mainApplicationWindow.rootViewController = mainTabBarController;
A very easy solution is to this problem, is to make a segue from your last UIVieController you want to be embedded in the UINavigationController to the one you want out of the UINavigationController.
Step 1.
Ctrl drag from the yellow icon on top of the UIViewController (embedded in the UINavigationController) to the UIViewController you want to segue to (out of the UINavigationController), and select "Present Modally"
Step 2.
Give the segue an identifier in storyboard
Step 3.
In your code, where you want to do the segue, put;
performSegue(withIdentifier: "yourSegueID", sender: self)
This will do the trick, and makes your storyboard more readable.
Here is what code I get online, and it does work on previous project that I develop.But in this project, self.navigationController is null when I NSLog it, and guys online talked about add some code in delegate file, but I found nothing in previous project also I am not very clear what code should I add there. Anyone can give me a hand?
UIViewController *next = [[self storyboard] instantiateViewControllerWithIdentifier:#"ViewCollection"];
[self.navigationController pushViewController:next animated:YES];
If UINavigationController is nil, it means that the view controller that you use (which you instantiate from a Storyboard) is not actually embedded within a UINavigationController.
In order to embed it into a UINavigationController, you need to drag and drop a UINavigationController into your Storyboard and then ctrl-drag from the UINavigationController to your custom view controller and set it as the rootViewcontroller of the UINavigationController.
as nburk said: you need a NavigationController with a RootViewController which is your view. and dont forget to set the NavigationController as Initial View Controller. This all is done in the IB.
first part of my question is basic understanding.
I believe the other viewControllers in the storyboard are in a "Non instantiated" form when application is launched, and are launched when they are sequed, please confirm?
Second part how do I programmatically instantiate a sibling UIViewController within the storyboard and optionally create a seque to it. I've found some code from Objective-C (pasting below) but looking for a solution in SWIFT.
MyViewController *myVC = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"MyViewController"];
Your first statement is true to a certain extent. Any controller connected to one that does get instantiated by a relationship segue or an embed segue will also be instantiated (like all the children of a tab bar controller). In your code snippet, you don't need to use storyboardWithName: if you're calling that method from a controller that was created in the same storyboard; you can just use self.storyboard.
var myVC = self.storyboard.instantiateViewControllerWithIdentifier("MyViewController")
I am very new to using Storyboards, and am trying to learn. In my app, I want to change from one view to another, modally, without pushing any buttons, i.e. timer runs down then performs the action. I added a notification observer in the main view, and in my storyboard, I added a new view controller, and associated the Custom Class with it called URLWebViewController. In code I wrote out:
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard_iPhone" bundle:nil];
URLWebViewController *myVC = (URLWebViewController *)[storyboard instantiateViewControllerWithIdentifier:#"URLWeb"];
[self presentViewController:myVC animated:YES completion:nil];
But I get the warning message
Incompatible pointer types sending 'URLWebViewController' to parameter of type 'UIViewController'
Like I said, I am very new to Storyboards, and here is what it looks like currently:
Your screenshot indicates you have not created a segue between the two view controllers. Do so by click-and-drag from one view controller to the other. In the attribute inspector, give your newly-created segue an identifier, i.e., a string that names it.
To trigger this segue programmatically, in your source view controller (the one you are segueing from) just call performSegueWithIdentifier and pass in the identifier you chose.
It's really simple! I didn't understand the order but let's say you want to pass from ViewController to WebViewController (the name from your storyboard)..Just ctrl-drag from ViewController to WebViewController to create a segue and select modal as the type.
Now click on the line that connects your view controllers and in the right panel give it an identifier. Now in your code just use the method performSegueWithIdentifier using the identifier you wrote.
I'm relatively new to iOS development. I am to move from one viewController to another I use a modal segue transition on button click. This is a game so i want to allow the user to click images to essential move the the app menus.
I have a main page that displays several images, on clicking one i want to be able to move to another view. Currently doing this with a modal segue is causing odd problems with my touchesEnded event where if, for example, i navigate to a page 3 times the touchesEnded event is fired 3 times.
Is there a better way for me to do this or am i just missing thing fundamental?
Thanks
Yes, I think you must make the the navigation controller your root view controller then push views accordingly
UINavigationController * nav = [[UINavigationController alloc] initWithRootViewController:YOUR_BASE_CONTROLLER]
self.rootViewController = nav;
this is in your app delegate.
Then in your action method
[self.navigationController pushViewController:secondViewController animated:YES]
Im assuming you are using the Storyboard to link VCs using segues.
Modal segues are great for simple transitions but really seem to limit what you can accomplish when they are just linked through SB. Ive found that creating an IBAction that includes the following for a VC segue will allow you to not only control your segues more efficiently but also allow you to have a clearer view of what is actually occurring during the transition.
-(IBAction)goToVc:(id)sender{
//Other code to take place during the segue here
//This will identify the Storyboard in use
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
//This will identify the View Controller to switch to
SecondViewController *vc2 = [storyboard instantiateViewControllerWithIdentifier:#"SecondViewControllerID" ];
[self presentViewController:vc2 animated:YES completion:NULL];
}
Every time you perform a modal segue, you lose the UINavigationController that you were previously using. What you need to do is embed a UINavigationController in the view that you are performing a modal segue to.
Check out a question I answered the other day to help you visualize more clearly what I'm talking about.