preface

Sometimes during development, we need to get the top ViewController of the current screen, and then manipulate that ViewController to do things like add a loading ring, a prompt box, etc.

Train of thought

I go up through the bottom ViewController until I find the top ViewController, That is, start with the rootViewController of UIApplication’s keyWindow (if there are more than one UIWindow you need to consider the selection of UIWindow.

In the search, consider that the current ViewController is UITabBarController and UINavigationController, respectively, Should also consider whether the current ViewController through presentViewController: animated: completion: modal shows other ViewController.

implementation

// UIViewController+TopViewController.h

+ (UIViewController * )topViewController {
    UIViewController *resultVC;
    resultVC = [self recursiveTopViewController:[[UIApplication sharedApplication].keyWindow rootViewController]];
    while (resultVC.presentedViewController) {
        resultVC = [self recursiveTopViewController:resultVC.presentedViewController];
    }
    return resultVC;
}

+ (UIViewController * )recursiveTopViewController:(UIViewController *)vc {
    if ([vc isKindOfClass:[UINavigationController class]]) {
        return [self recursiveTopViewController:[(UINavigationController *)vc topViewController]];
    } else if ([vc isKindOfClass:[UITabBarController class]]) {
        return [self recursiveTopViewController:[(UITabBarController *)vc selectedViewController]];
    } else {
        return vc;
    }
    return nil;
}

Copy the code

use

UIViewController *vc = [UIViewController toViewController];
Copy the code