UINavigation pushing a new root controller

2019-03-01 10:19发布

问题:

I am trying to push a new root controller to a navigation stack, but using a side reveal menu.

My app delegate has the following:

    welcomeViewController = [[MyWelcomeViewController  alloc] initWithNibName:@"MyWelcomeViewController" bundle:nil];
navController = [[UINavigationController alloc] initWithRootViewController:welcomeViewController];
navController.navigationBarHidden = YES;

// Then we setup the reveal side view controller with the root view controller as the navigation controller
self.revealSideViewController = [[PPRevealSideViewController alloc] initWithRootViewController:navController];
[self.revealSideViewController setDirectionsToShowBounce:PPRevealSideDirectionNone];
[self.revealSideViewController setPanInteractionsWhenClosed:PPRevealSideInteractionContentView | PPRevealSideInteractionNavigationBar];

// Then we make the window root view controller the reveal side view controller
self.window.rootViewController = self.revealSideViewController;

Once the welcome view controller is displayed, the user logs in. Once logged in the following process runs again from the App Delegate.

self.navController.navigationBarHidden = NO;
[self.navController setTitle:@"Home"];
[self.navController pushViewController:homeViewController animated:NO];

I then have a side view controller setup which is a table view with custom cells setup.

When a row is selected I need to push a new root controller onto the navigation controller. I try this by using the following in the table view for the cell selected.

MyAccountViewController *accountViewController = [[MyAccountViewController alloc] init];
[self.navigationController setViewControllers:[NSArray arrayWithObject:accountViewController] animated:NO];

Unfortunately this does not do anything. If I add the code to the App Delegate and then call the method from the table view controller then it works, however not from the .m file for the table view itself. Adding a log I can see the above is run, just does not do anything.

I am unsure if I need to do anything different on the above. For example, completely pop the views currently shown, then create the navigation controller and PPRevealSideViewController all over again. If I am supposed to, I am unsure how to pop all the current views to then push the new to the window, not from the AppDelegate.

The reason I do not want this in the App Delegate is because it is the incorrect way to approach this, and I would then need a separate method for each new root controller I would like to push from the menu, so the App Delegate would become very large.

回答1:

Check UINavigationController.h:

@interface UIViewController (UINavigationControllerItem)
@property(nonatomic,readonly,retain) UINavigationController *navigationController; // If this view controller has been pushed onto a navigation controller, return it.

It means when you do myViewController.navigationController you will either get nil if myViewController is not pushed to any navController or the navController reference myViewController is pushed into.

As I understand your tableViewController is not pushed into the navController stack, that means you can't get the navController with tableViewController.navigationController. Instead you'll need to use anyViewControllerInTheStack.navigationController or if the navController is the rootViewController of your keyWindow, by

((UINavigationController*)[[UIApplication sharedApplication] keyWindow].rootViewController)


回答2:

Add something like this to your AppDelegate.h:

#define XAppDelegate ((AppDelegate *)[[UIApplication sharedApplication] delegate])

Now you can access any iVar of AppDelegate from any .m file in your project.

 MyAccountViewController *accountViewController = [[MyAccountViewController alloc] init];
 [XAppDelegate.navController pushViewController:accountViewController animated:NO];

Make sure you add the correct imports. One more thing: It's good to pop the login window from your navcontroller once you are done Logging in.

Hope this helps.