Best practice for switching between UINavigationCo

2019-03-30 06:14发布

问题:

In our storyboard we have multiple UINavigationController stacks. For example, the LoginViewController stack is completely separate from the SWRevealViewController stack.

What's the best practice for switching between them? When I press the logout button (the logout button is on the SWRevealController stack) and then try to present the LoginViewController stack, I get an error like this:

Warning: Attempt to present LoginViewController on SWRevealViewController whose view is not in the window hierarchy!

Even though I'm specifically setting self.window.rootViewController to the Login View Controller's UINavigationController in App Delegate like this:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Spitfire" bundle:nil];
UINavigationController *nav = [storyboard instantiateViewControllerWithIdentifier:@"LoginNavigationController"];
LoginViewController *loginVC = [storyboard instantiateViewControllerWithIdentifier:@"LoginViewController"];

self.window.rootViewController = nav;
[nav presentViewController:loginVC animated:NO completion:nil];    

Is there a way I can "dismiss" the current UINavigationController stack and use a new one? Or maybe I shouldn't be calling this code in my app delegate?

回答1:

I had not played with SWRevealViewController before your question, so my previous response was a little more generic. I've created a sample app here that does its best to throw around as many navigation stacks as possible; I'm sure I've covered your use case.

A few things I'll draw your attention to:

  1. The "main flow" from my previous answer is right smack in the middle of the storyboard; that should help orient you.

  2. SWRevealViewController.m can be used in conjunction with Storyboards and has a very clever hack to do so, but the documentation for it is buried in the implementation. It took me a while to figure out what the hell was happening, but my example app illustrates the usage (two segues, one for "front" and the other for "back", could have a third for "right").

  3. The app's main flow gets completely swapped out for the alternate flow. This is by design of SWRevealViewController. You are essentially switching to an entirely new app.

  4. All sub-flows that are presented modally disrupt the flow.

  5. The author of SWRevealViewController has not provided UIStoryboardSegue subclasses for the replacement of front, rear, and right view controllers. This would be trivial to implement, but I've elected to do the swapping manually in FHKSettingsViewController's implementation.

  6. I repeated code and made dinky classes to make sure what I was doing was obvious.



回答2:

You should wait to call presentViewController until viewDidAppear on rootViewController.

See here for more discussion: whose view is not in the window hierarchy



回答3:

Edit:

call presentViewController from your UINavigationcontroller's rootviewController in viewDidAppear: method

-(void)viewDidAppear:(BOOL)animated {

   LoginViewController *loginVC = [storyboard instantiateViewControllerWithIdentifier:@"LoginViewController"];
   [self presentViewController:loginVC animated:NO completion:nil];
   [super viewDidAppear:YES];
}