I have a viewController that is usually (most often) accessed by using a push segue. This viewController needs to be embedded in a UINavigationController. So typically, this is no problem. The push segue manages pushing the viewController, and therefore the viewController has it's UINavigationController.
My issue is that in a few cases, I'd like to present this same exact viewController using a modal segue. When I do this, the viewController is not embedded in a navigationController. Is there a way to do this using segues?
I know this can be done purely in code without segues by creating a UINavigationController, setting the rootView as the viewController and then presenting that modally. That can be done using code like this :
MyViewController *viewController = [[MyViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:viewController];
[self presentModalViewController:navController animated:YES];
But how do I do this same thing but using Segues?
Update
For further clarity, here is some code to supplement how I used the accepted answer in the prepareForSegue method.
When Using Modal Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue destinationViewController] isEqualToString:#"Modal to MyVC"])
{
UINavigationController *nav = [segue destinationViewController];
MyViewController *vc = [nav topViewController];
//setup vc
}
}
When Using Push Segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue destinationViewController] isEqualToString:#"Push to MyVC"])
{
MyViewController *vc = [segue destinationViewController];
//setup vc
}
}
In your Storyboard, you can embed a ViewController in a Navigation Controller by selecting the View Controller and then picking from the menu at the top Editor->Embed In->Navigation Controller. From another view controller, you control drag to this Navigation controller to set up the modal segue. You can also control drag to the original View Controller to set up segues to it without the Navigation Controller.
Related
sorry for my bad English
i need to pass data from my First View Controller to Front View Controller of SWRevealViewController
in my First View Controller i do this code
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"menu"]) {
SWRevealViewController *sw = (SWRevealViewController *) segue.destinationViewController;
// error is here i get nav with nil
UINavigationController *nav = (UINavigationController *)sw.frontViewController;
FrontViewController *home = (FrontViewController *) nav.topViewController;
home.passed_student = selected_student;
}
}
In storyBord no object(view controller) is created untill it is presented using segue or accessed some other way so here in your code your are presenting the SWRevealViewController but try to access the object of FrontViewController which is not in memory.
So first you should pass your selected_student to your SWRevealViewController then from here to FrontViewController because you can access the object of FrontViewController from here during presenting it using segue. This is the simplest way of doing it.
I want to pass the variable " uid " between the FirstViewController and SecondViewController, so I used the following code to pass it. It successfully pass it, but the problem it hides the NavigationBar and the TabBar !
How can I solve it?
SecondViewController *vc2 = [self.storyboard instantiateViewControllerWithIdentifier:#"SecondViewController"];
vc2.uid = uid;
[self.navigationController pushViewController:vc2 animated:YES];
Why dont you use storyboard segues to solve this? Just embed you view controller on a Navigation View controller and call performSegueWithIdentifier function.
Just add prepareForSegue function to your class and set uid there:
- (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) sender
{
if([segue.identifier isEqualToString:#"secondViewSegue"])
{
//**OPTION A**: If you are using Push segue
SecondViewController *secondVC = (SecondViewController
*)segue.destinationViewController;
//**OPTION B**: ***ELSE, If you are using a Modal segue
UINavigationController *navController = (UINavigationController*)segue.destinationViewController;
SecondViewController *secondVC = (SessionViewController *)navController.topViewController;
//END OF OPTION B
secondVc.uid = uidValue;
}
}
In the following setup, Button 1 calls First VC and Button 2 calls Second VC
Currently, I use the following code to call SecondVC by tapping Button 2.
MainVC.m
#implementation MainVC()
....
UINavigationController *navController = [self.childViewControllers objectAtIndex:0];
SecondVC *secondVC = [self.storyboard instantiateViewControllerWithIdentifier:#"second"];
[navController pushViewController:secondVC animated:YES];
The code above displays SecondVC just fine. However, in the First VC there are statements that need be executed before "Second VC" is presented, that are being skipped!
I execute these statements in First VC inside -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender. When the Next Button is tapped in the First VC, all the statements execute because it triggers prepareForSegue before presenting SecondVC. This step is skipped when the code above is used.
Extra Info:
A) Though a Navigation Controller, Main VC in my app does not show the navigation bar in my app. I believe this would be against HIG to display two navigation bars on an iPhone. I show it here to identify Main VC.
B) There are textFields in FirstVC that User fills out. If I just copy the code, will it read and save the data from textFields.text?
Question: How can I call prepareForSegue from First VC when Button 2 is tapped in MainVC? or is there another approach to this?
You could try something like the following:
UINavigationController *navController = [[self childViewControllers] objectAtIndex:0];
UIViewController *vc = [navController topViewController]
if ([vc isKindOfClass:[FirstVC class]]) {
FirstVC *firstVC = (FirstVC *)vc;
SecondVC *secondVC = [[self storyboard] instantiateViewControllerWithIdentifier:#"second"];
// Copy and read data from [[firstVC textField] text] to secondVC.
[navController pushViewController:secondVC animated:YES];
}
Basically, i'm using the prepareForSegue method to transition to another view within my storyboard, my view had to be embedded in a navigation controller in order to display the navigation bar so I am passing variables in such a way:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"exploreAddSelected"]){
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
AddTableViewController *controller = (AddTableViewController *)navController.topViewController;
controller.tagName = tagName;
}
}
My issue is I need to be able to set some method values in the actual view controller when using the prepareForSegue method, as you can do when using pushViewController as below:
DetailViewController *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"DetailViewController"];
detailViewController.tagName = tagName;
[detailViewController setCurrentHashtag:nil];
[navigationController pushViewController:self.detailViewController animated:YES];
I need to be able to set the "setCurrentHashtag" method, that is declared in the view controller that the segue "exploreAddSelected" goes to. How would I do this?
The answer to this is actually extremely obvious, but it takes me to ask the question to realise the answer myself.
You can simply set:
controller.currentHashtag = nil;
Where currentHashtag is a newly declared instance in the view controller.
Then in the actual view controller set:
[self setCurrentHashtag:currentHashtag];
Just add the currentHashtag to the method.
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if([segue.identifier isEqualToString:#"exploreAddSelected"]){
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
AddTableViewController *controller = (AddTableViewController *)navController.topViewController;
controller.tagName = tagName;
[controller setCurrentHashTag:nil]; //add this line
}
}
I'm not sure what you are doing here. If the segue points to a view controller directly (and nor via another navigation controller), you do not need the mapping to topviewcontroller, but use the destinationcontroller directly.
I have a storyboard with a UINavigationController. The root view controller of the navigation controllers is called rootViewController.
I am trying to programmatically change the view controller (depending on other conditions) to another view controller called loginViewController.
I am trying to do this in the viewDidLoad from the rootViewController like this:
- (void)viewDidLoad
{
[super viewDidLoad];
loginViewController *viewController = [[loginViewController alloc] init];
[self.navigationController pushViewController:viewController animated:YES];
}
I am not getting any errors but it's not working.
It just loads the navigation controller with the top nav back button but the rest of the screen is black. It's like it's not loading any view controller.
I am trying to figure out what I am doing wrong.
Any help with this would be great.
Thanks
First add loginViewController class in storyboard and and connect ViewController class to loginViewController class and give identifier name as "identifier_Name".
- (void)viewDidLoad
{
[super viewDidLoad];
[self performSegueWithIdentifier:#"identifier_Name" sender:nil];
}
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if([[segue identifier] isEqualToString:#"identifier_Name"])
{
loginViewController *viewController = [segue destinationViewController];
}
}
If you're using storyboard, create your login view in the storyboard, link your rootVC to the loginVC with a segue, choose an identifier (for example: "goToLogin"). and then to go in the login view, and use:
[self performSegueWithIdentifier:#"goToLogin" sender:self];