I have achieved this but I am asking more if I did this right. I have been immersed in the apple documentation and iOS programming books. Since then I have fully reworked my app for reusability and all that good stuff.
Now I have a main UIViewController named RootController that handles a UINavigationController and a custom MenuController. I decided that UIViewController containment was the best approach for my RootController.
RootController ---> UINavigationController
---> MenuController
Now a problem occurred where I needed some of the sub UIViewControllers in the UINavigationController to communicate with the main RootController.
RootController ---> UINavigationController --> UIViewController
^_____________________________________________|
What I decided to do was extend UIViewController with a category.
UIViewController+RootController.h
@interface UIViewController (RootController)
@property (nonatomic, readonly) RootController *rootController;
@end
UIViewController+RootController.m
@implementation UIViewController (RootController)
- (RootController *)rootController {
static RootController *rootControler;
if(rootControler == nil) {
UIViewController *vc = self;
while((vc = vc.parentViewController)) {
if([vc isMemberOfClass:[RootController class]]){
rootControler = (RootController *)vc;
break;
}
}
}
return rootControler;
}
@end
When [self rootController] is called by any UIViewController it will loop through the parent view controllers until it find one that matches RootController, it will then return the match. I also made the property static so it was only looked up once.
So my question is was this the right approach I made? I was trying to make something similar to UIViewController’s navigationController method.
I need access to the main root controller so I can handle the MenuController from any view within my app.
Your solution seems correct but not so clean imho.
In similar situations I usually prefer to obtain a reference in “inverse” method, using the AppDelegate.
For Example:
vc is a reference to your root view controller.
Take care because the root view controller of the window can change (if you change it :-). So, in this case, you should change your aproach (for example adding a @property to your AppDelegate and make your RootController setting this property on load)