4

It's common to see example code that walks the view hierarchy from root to get a pointer to a particular view controller, like this:

UITabBarController *tabBC = (UITabBarController *)self.window.rootViewController;
UINavigationController *navC = [tabBarController viewControllers][0];
MyCustomTableViewController *myVC = [navigationController viewControllers][0];

This is hopelessly fragile, breaking every time the storyboard ordering is revised. What seems to be needed is a UIViewController method like:

/*! recurse through child VCs to find instances of class */
-(NSArray*) childVCsOfClass:(Class)targetClass;

or possibly:

 -(NSArray*) childVCsPassingTest: // some useful block

I wrote this scrap to accomplish the simpler case of finding the first instance, but still suspect I'm overlooking something obvious:

/*! Search through hierarchy for correct view controller
    TODO: Should be a class extension of ViewController, assuming Apple didn't write it yet
    TODO: The double loops are suspect...
*/
UIViewController* FirstChildViewControllerMatchingClass(UIViewController* rootVC, Class targetClass) {
    UIViewController *thisController = rootVC;
    UIViewController* foundInstance = nil;

    if([thisController isKindOfClass:targetClass]) {
        return thisController;  // found it.
    }
    // Special case all the collections, etc.
    if([thisController respondsToSelector: @selector(viewControllers)]) {
        for(id vc in [(id)thisController viewControllers] ) {
            foundInstance = FirstChildViewControllerMatchingClass(vc,targetClass);
            if(foundInstance) {
                return foundInstance;   // found it in the tabs
            }
        }
    }
    // chug through other possible children
    if(thisController.childViewControllers) {
        for(UIViewController* kids in thisController.childViewControllers ) {
            foundInstance = FirstChildViewControllerMatchingClass(kids,targetClass);
            if(foundInstance) {
                return foundInstance;
            }
        }
    }
    // have I missed other possible children...?
    return nil;
}

I'm not particularly asking for reviews of this code, which I've not even tested, I'm trying to figure out if Apple (or someone else) already wrote a sturdy and complete version and I've just not searched the right documents. (OTOH constructive criticism is welcome ;)

Taryn
  • 1,670
  • 1
  • 15
  • 22

0 Answers0