Reputation: 1828
I have a login view. If the login is successfully done, I want my program, navigate to the main window.
I used modal segue, between the login view and main view.
However, after reaching main view, I want to use push segues and unfortunately I'm facing the following exception:
Terminating app due to uncaught exception 'NSGenericException', reason:
'Could not find a navigation controller for segue 'routeList'.
Push segues can only be used when the source controller is managed by an
instance of UINavigationController.'
Here is the functions that I gave the command for "modal segue" in "login controller":
//LoginController.m
- (IBAction)loginTapped:(id)sender {
[self performSegueWithIdentifier:@"login" sender:@{@"foo": @"bar"}];
}
-(void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([[segue identifier] isEqualToString:@"login"])
{
MainController *vc = segue.destinationViewController;
vc.uuid = userUuid;
}
}
Here are the functions that I use to perform "push segue" in the "main controller". I want to perform a push segue here and I face the exception in this part.
//MainController.m
- (IBAction)actionGo:(id)sender {
[self performSegueWithIdentifier:@"routeList" sender:self];
}
In fact, I have a navigation controller before "login view". So why does it couldn't find a "navigation controller"?
If I use modal segue, it works. So why doesn't it work for push segue?
Edit 1 - My storyboard:
Edit 2 - It is suggested to embed main controller into a navigation controller (Click the source controller of the routeList segue and under the Editor menu select Embed In > Navigation Controller). Now, my story board is given below and I'm facing this error now:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException',
reason: '-[UINavigationController setUuid:]: unrecognized selector sent to
instance 0x17da9df0'
I'm passing a value from login controller to main controller. When I add a navigation controller I couldn't pass this value. How can I pass this value?
Storyboard when MainController is embedded into a navigation controller:
SOLUTION IN MY WORDS:
Thanks to the people that shared their answered in this thread :) I solved the problem. In the navigation controller stack, if I put a modal segue, somehow the link is broken and rest of the views are not part of the navigation controller. So, I made all segues as "push style". Then In the MainController.m I removed the back button as follows:
-(void)viewDidAppear:(BOOL)animated{
[self.navigationItem setHidesBackButton:YES animated:NO];
}
Upvotes: 0
Views: 5984
Reputation: 13181
Please note the following recommendations based on your error:
Terminating app due to uncaught exception 'NSGenericException', reason: 'Could not find a navigation controller for segue 'routeList'
Recommendations
In fact, I have a navigation controller before "login view". So why does it couldn't find a "navigation controller"?
A picture of the storyboard would help assess the issue. You can check the availability of the navigation controller several ways. One way to ensure that the source controller is embedded in a navigation controller would be to click the source controller of the routeList segue and under the Editor menu select Embed In > Navigation Controller
By the way, if I use modal segue, it works. Why doesn't it work for push segue?
Push segues require a navigation controller while modal segues do not require a navigation controller. Here is a related question that will better explain the differences (stack overflow link).
UPDATE 1:
You mentioned that you also want to pass values between controllers. On the target VC create a property to hold the UserID. On your source view controller you will want to set the value of the target property and pass the data in your prepareForSegue method. Here is a link on how to do this from another SO Q&A.
UPDATE 2
You mentioned that your segues are push segues but the picture shown in the question is not indicating this... Please note the icons for push segues as outlined in my image below. You will also want to make sure that you name both of your converging segues. I've called my push segues routeA and routeB.
I hope this helps.
Upvotes: 1
Reputation: 119031
It doesn't work because you are triggering the routeList
segue from a controller which is presented modally and not contained in a navigation controller.
You probably want to swap your hierarchy around so that the main view is in the nav controller which is the window root view controller and the login screen is presented modally (and dismissed when the login is complete).
Start with something different: remove all modal segues and make them push. Next, in the main view controller, implement viewDidAppear:
to get the navigation controller and set its view controllers to just @[ self ]
(which will remove the login view controllers). This should remove your immediate issue.
Upvotes: 1