问题
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];
回答1:
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.
回答2:
In your App Delegate (or in response to your edit, any persisting singleton will work, yes), create properties to hold your View Controller instances.
@property (nonatomic, strong) MenuViewController *menuViewController;
... etc for all your vc's.
Whenever you initialize them later, set this property on the App delegate to hold the VC.
MenuViewController *menuVC = [[MenuViewController alloc] init];
AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
appDel.menuViewController = menuVC;
Now you can get this instance any time you need to present it. You can also set any properties on the menuViewController that you want to keep in memory.
Note: Be conscious of being a good memory citizen. Write didReceiveMemoryWarning methods to release anything you can easily reload when the VC becomes visible again so that you don't crash your app from holding too many things in memory at once.
回答3:
You should have one class (possibly the app delegate) which creates your container structure. It has access to the view controllers that are created. Your table view controller and navigation controller may not both exist initially but the class which creates everything initially should 'build the bridge' between the structures by passing a reference of the navigation controller or the content view controller to the table view controller or the menu view controller. That reference should be stored in a property and will allow you to cleanly present your view controller.
This kind of setup is preferable to navigating through parentViewController or similar links as that will lead towards tying you to a particular structure in a non-transparent way.
Or, in your storyboard, you can just add an IBOutlet property and make the connection directly there (if all of the view controllers are created up front when the storyboard is loaded).
来源:https://stackoverflow.com/questions/17474652/pushing-a-view-controller-using-another-uinavigationcontroller