I am trying to call a segue in my iOS app but am getting the error
Could not find a navigation controller for segue ___
I determined that the issue is that when I try to check the current visibleViewController, it is not the ViewController that the segue is linked to:
if(self.navigationController.visibleViewController == self){
[self performSegueWithIdentifier:#"login_success" sender:self];
}else{
NSLog(#"LoginViewController is not currently visible");
}
My question is, how can I set the correct view controller so I can call the segue?
Here is all my code:
LoginViewController: (The first ViewController)
-(IBAction)registerClick:(id)sender{
// open up registration
[self performSegueWithIdentifier:#"registration" sender:self];
}
Registration ViewController (the Modal ViewController)
-(IBAction)finish:(id)sender{
// return back to login view controller
[self dismissViewControllerAnimated:YES completion:nil];
}
LoginViewController segue attempt:
if(self.navigationController.visibleViewController == self){
[self performSegueWithIdentifier:#"login_success" sender:self];
}else{
NSLog(#"LoginViewController is not currently visible");
}
Related
I have one button (back button) on a view controller. Simple so far.
I have 2 view controllers with a table on each one.
if a user selects a row from either table it goes to the view controller with the back button on.
The back button needs to go back to the original view controller that the user was on when they selected the row.
I was considering unwind segues for this which is fine, but I cannot add two segues to one button. One for return to one table view and a return for the other table view dependent on which table view they used to access the view controller.
Any ideas ?
As Volk explained,
-(IBAction)devDismiss
{
NSLog(#" ------- dev dismiss .....");
// for a custom segue unwind, you must do this...
[self performSegueWithIdentifier:#"specialWord" sender:self];
// "specialWord" is the identifier set on storyboard for the
// custom unwind segue
/* for a "default" unwind segue, do this...
[self dismissViewControllerAnimated:YES completion:nil];
Note, if you used a push segue, you should use
[self.navigationController popViewControllerAnimated:YES]
If you used a modal segue, you should use
[self dismissViewControllerAnimated:YES completion:nil] "
*/
}
Note that indeed, you must also use "specialWord" in your segueForUnwindingToViewController: override, which will be in the DESTINATION (that is to say the ORIGINAL) view controller, the one underneath, that is to say.
-(UIStoryboardSegue *)segueForUnwindingToViewController:
(UIViewController *)toViewController
fromViewController:(UIViewController *)fromViewController
identifier:(NSString *)identifier
{
NSLog(#"we're in _your class name_, segueForUnwindingToViewController %#",
identifier);
// for some unwinds, we have a custom unwind we want to use.
// so, check the identifier:
if ([identifier isEqualToString:#"specialWord"])
{
YourCustomUnwindSegue *sg = [[YourCustomUnwindSegue alloc]
initWithIdentifier:identifier
source:fromViewController
destination:toViewController];
return sg;
}
// don't forget the break-away "return" inside any macthes.
// NSLog(#"note, if this message appears, it's likely you have a typo
// somewhere for 'specialWord' - unless you genuinely have a situation
// where it will also fall through to the 'default' unwind segue :O ");
// BE SURE TO return the default unwind segue otherwise
return [super segueForUnwindingToViewController:toViewController
fromViewController:fromViewController
identifier:identifier];
}
I have created a single view based application. I was wanting to overlay UIViewControllers as I needed them, for instance like a modal view thing where if some values are populated then load the next view until you do something there and you can come back.
This is the code I have
- (void) viewWillAppear:(BOOL)animated {
NSMutableDictionary *tempPrefs = [prefsController readPrefs];
NSString *tempName = [tempPrefs objectForKey:#"Name"];
NSString *tempProduct = [tempPrefs objectForKey:#"Product"];
// usedbefore so skip first view (first view == login view
if ((tempName.length != 0) && (tempProduct.length != 0)) {
// you have values, enter new room without checking
[self loadGetProListViewController];
}
}
- (void) loadGetProListViewController {
[self dismissViewControllerAnimated:NO completion:nil];
getProListViewController = [[GetProListViewController alloc] initWithNibName:#"GetProListViewController" bundle:nil];
[self presentViewController:getProListViewController animated:YES completion:nil];
}
However once this method has been reached its executed but nothing is happening..
If anyone could tell me how to create modal viewControllers or some description that would be greatly appreciated.
First you should be aware of UIViewController lifecycle to have an idea where you are able to present different UIViewController
Also I guess you have a bit incorrect architecture (maybe I wrong).
Let's imagine you have firstViewController on which -viewDidAppear method you present getProListViewController
Don't you think that presenting intermediate firstViewController is odd?
I'd reather you would move your if clause to level up. F.e:
/ usedbefore so skip first view (first view == login view
if ((tempName.length != 0) && (tempProduct.length != 0)) {
// present your getProListViewController
} else {
// present your "FirstViewController" (login or whatever)
}
And you haven't faced with your issue at the beginning
Try this
[self presentModalViewController: getProListViewController animated:YES];
instead of your presentviewcontroller
[self presentViewController:getProListViewController animated:YES completion:nil];
I am working on an iPad app that has a login controller which segues into a view controller. The login controller is declared thusly:
#interface LoginController : UIViewController <UITextFieldDelegate>
and the storyboard has (as expected), a username and password text field and a button for authentication and logging into the main app. The button calls the shouldPerformSegueWithIdentifier(...) function and the view switches from the login view to the main view.
I would like to also mimic this programmatically, when the user hits return on the password text box. I've trapped the event, but I can't seem to get the switchover to happen. The code I'm using is:
if (theTextField == self.password)
{
BOOL loginSuccessful = [self shouldPerformSegueWithIdentifier:#"switchToViewer" sender:self];
if (loginSuccessful == YES)
{
[self dismissViewControllerAnimated:YES completion:^{
NSLog(#"I should be dismissing here!\n");
}];
}
}
However, the view never gets dismissed. I should note that this is on iOS 7, I don't know if that matters. Any ideas?
EDIT: My workaround for now is to spoof the button touch event:
[self.signIn sendActionsForControlEvents: UIControlEventTouchUpInside];
Hacky, but it works :)
[self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
I am trying to use popToViewController and it I keep getting the error "Tried to pop to a view controller that doesn't exist"?
I am in a Settings view and when the user clicks "Sign Out" I dismiss the Settings VC and segue back to the mainView where an unwind segue method is called. In the unwind segue method I call the following.
-(IBAction)endSettingsViaLogout:(UIStoryboardSegue *)segue {
//[self performSegueWithIdentifier:#"mainToLoginSegue" sender:self];
[self.navigationController popToViewController:[self.navigationController.viewControllers objectAtIndex:1] animated:YES];
//[self.navigationController popViewControllerAnimated:YES];
DLog(#"User finished with search");
}
When the poptoVC is called I get the "Tried to pop to a view controller that doesn't exist".
I NSLog the self.navigationController.viewControllers and I can see the stack of VC's and the one I want to pop to is in there?
/// UPDATE //////
Ok here is what I have found. If my segue to Settings is a regular "push" segue then the code works and I get popped back to where I want. If I do a custom segue, having come from the left side of the screen then it stops working. Even with the custom segue the self.navigationcontroller.viewcontrollers shows its in the stack. So why can't I pop back to it? Or how can I pop back to it with the custom segue?
Do I get the view controller hierarchy right?
On your basis UINavigationViewController you have set a main view controller as root view controller.
Then a settings view controller has been pushed upon this.
Via "Sign out" the settings view controller is being segued back to the main view controller.
If so, you are actually trying pop "back" to a view controller, that does not exist, since you already have reached the root view controller of your navigation controller stack. In this case, all previously initialized controllers have been popped from the stack and you would have to reinitialize and push the desired view controller.
If I am missing some important point, it would be helpful, if you would describe your actual view controller stack at the moment the "Sign out" option is available. Furthermore, what exactly is printed on the console if you log the self.navigationController.viewControllers array?
well that basically tells objectatindex 1 does not exist:
things to try:
objectatindex:0
or
nslog(#"%d",[[self.navigationController.viewControllers]count]);//add it before the popline and see if it works
if its the topview controller then try below:
[navigationController topViewController] instead
NSArray *viewControllers = [[self navigationController] viewControllers];
for( int i=0;i<[viewControllers count];i++)
{
id obj=[viewControllers objectAtIndex:[viewControllers count]-i-1];
if([obj isKindOfClass:[OrderCheckOutViewController class]]){
[[self navigationController] popToViewController:obj animated:YES];
return;
}
}
you can use the snippet to pop out to targetVC's next viewController in the navigationController's stack.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
BOOL findIt = NO;
UIViewController *targetVC = nil;
for (UIViewController *subVC in self.navigationController.viewControllers) {
if (findIt) {
break;
}
if (subVC == xxx) {
findIt = YES;
}else{
targetVC = subVC;
}
}
[self.navigationController popToViewController:targetVC animated:NO];
});
Sorry for bad english.
I have MainViewController and TabBarController with two Views in storyboard.
when i push button (using modal segue) in my MainviewController - app switch to firstTabBarView or secondTabBarView depending on conditions. it works fine but after that i lost my TabBarControls at the bottom of any of my tabBarViews.
UPD: action after bar Button pressed
-(IBAction)barButtonPressed:(id)sender
{
if (condition !=0 ) {
[self performSegueWithIdentifier:#"segue1" sender:nil];
} else {
[self performSegueWithIdentifier:#"segue2" sender:nil];
}
}
It's working as advised. A modal segue is a "fullscreen segue" and covers your standard navigation stack.
If you simply want to change the selected viewcontroller, use
[yourTabBarControllerInstance setSelectedIndex:index];