简体   繁体   中英

how to push a view controller to a navigation controller in a tab bar in iOS

I have a tab bar controller with a navigation controller per tab. The nav controllers have view controllers. I then have a Login View Controller not connected to the tab bar controller that I call with the code below if a user needs to login or logs out.

I am seeing some strange behavior when I try to conditionally push a view controller based on if a user is logged in or not.

My logic looks like this:

if(currentUser){
}else{

        LoginViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:@"Login"];
        svc.hidesBottomBarWhenPushed = YES;
        [self.navigationController pushViewController:svc animated:YES];

    }

When the view is pushed it look as if the the Login View is pushed and another Login View is pushed on top of it.

For logout I have the same code in a segue:

if ([segue.identifier isEqualToString:@"LogoutView"]) {

        [self logOut];
        LoginViewController *svc = [self.storyboard instantiateViewControllerWithIdentifier:@"Login"];
        svc.hidesBottomBarWhenPushed = YES;
        [self.navigationController pushViewController:svc animated:YES];
    }

In this instance I see the same double push and each time I click my login button it pushes another Login View. This happens infinitely. I then get the warning:

Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.

When I press back in the navigation, the app crashes with the error:

NSInvalidArgumentException', reason: 'Can't add self as subview'

Am I not correctly pushing the login view controller?

Segues instantiate new controllers, and perform the transition form the source controller to the destination controller. Therefore, you should neither be instantiating the controller in code, nor pushing it with pushViewController:animated:. If the buttons (rather than the controller) are triggering the segues, then you only need to get a reference to the destination controller (segue.destinationViewController), and use that to hide the bottom bar,

-(void)prepareForSegue:(UIStoryboardSegue *) segue sender:(id) sender {

    if ([segue.identifier isEqualToString:@"LogoutView"]) {

            [self logOut];
            LoginViewController *svc = segue.destinationViewController;
            svc.hidesBottomBarWhenPushed = YES;
    }
}

If you need to do this conditionally, then the segue should be connected directly from the controller, not a button. Then you need to call performSegueWithIdentifier: in some method where you have the logic to determine which (or whether a) segue should be performed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM