Search code examples
iosobjective-ccocoa-touchios5ios6

Pushing a View Controller using another UINavigationController


This is how my app looks like. I've subclassed UINavigationController in a way that when you tap a button on something similar to a navigation bar the MenuViewController slides out. How can I push \ present one of the my VC1, VC2, VC3 into ContentViewController from didSelectRow that's inside the UITableViewController menu?

                -> SlidingViewController
                 /                   \
            Container             Container       
                |                     |
        MenuViewController    ContentViewController
                |                      |
     UITableViewController   SubClassed UINavigationController
                                  |    |    |    |
                                 VC1  VC2  VC3  VC4

Usually I do something like the next code but with the situation above I'm not sure how I can push a new view controller if i'm not in the same UINavigationController.

NSString * storyboardName = @"MainStoryboard_iPhone";
NSString * viewControllerID = @"ViewID";
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
MyViewController * controller = (MyViewController *)[storyboard instantiateViewControllerWithIdentifier:viewControllerID];
[? presentViewController:controller animated:YES completion:nil];

Edit:

Possible solution that works but I'm not sure if that's a good way to do it. I've used a singleton to save my Navigation Controller and use it later.

Inside my ContentViewController:

[DataManager sharedDataManager].navController = self.navigationController;

Inside my didSelectRow in MenuViewController :

[[DataManager sharedDataManager].navController presentViewController:controller animated:YES completion:nil];

Solution

  • You don't want MenuViewController to have knowledge of anything in the view controller hierarchy other than itself and its children. You have two options that allow for this good design.

    1. Use delegation

    First, you want to have a MenuViewControllerDelegate that has, for example, menuViewController:didSelectOption:. When something happens in the menu, MenuViewController will send an appropriate delegate message to its delegate object.

    Now to listen for that delegate message, you will need a controller object (could be a view controller or just a regular NSObject) that conforms to MenuViewControllerDelegate and sets the delegate of MenuViewController to itself. This controller object will then handle any delegate messages that MenuViewController may send, e.g. push a new view controller onto ContentViewController when a menu option is selected.

    2. Post notifications

    This is the more fragile of the two. You would use notifications if you have lots of things all over your view controller hierarchy that need to know when something happens in the menu.

    So MenuViewController would post a notification, perhaps named MenuViewControllerDidSelectOptionNotification, and then any interested receivers that have registered for that notification would then receive the notification and do their thing.