SoFunction
Updated on 2025-04-11

Detailed explanation of the correct way to easily get the current controller in iOS

background

During the development process, we often need to obtain the current window, rootViewController, and the currently displayed visibleController requirements. If the .m implementation is not in the current view, we need to quickly obtain the current controller. In this case, we need to first make a layer of encapsulation. I usually implement it through a Category written by UIViewController. The implementation is also very simple. We only need to master a few methods of the controller.

Get the root controller

+ (UIViewController *)jsd_getRootViewController{

  UIWindow* window = [[[UIApplication sharedApplication] delegate] window];
  NSAssert(window, @"The window is empty");
  return ;
}

It is very simple here. Get the delegate of the current UIApplication through a singleton and you can easily get the rootViewController through window.

Get the current page controller

+ (UIViewController *)jsd_findVisibleViewController {
  
  UIViewController* currentViewController = [self jsd_rootViewController];

  BOOL runLoopFind = YES;
  while (runLoopFind) {
    if () {
      currentViewController = ;
    } else {
      if ([currentViewController isKindOfClass:[UINavigationController class]]) {
        currentViewController = ((UINavigationController *)currentViewController).visibleViewController;
      } else if ([currentViewController isKindOfClass:[UITabBarController class]]) {
        currentViewController = ((UITabBarController* )currentViewController).selectedViewController;
      } else if ([currentViewController isKindOfClass:[UISplitViewController class]]) { // When compatible with Ipads are required        currentViewController = ;
      } else {
        if () {
          currentViewController = ;
        } else {
          return currentViewController;
        }
      }
    }
  }
  
  return currentViewController;
}

Here we will talk about the implementation idea. If we want to get the current controller without coupling with the controller, we basically search through the rootViewController. After getting the rootViewControler through the above method, we first look at the presentedViewController. Because the controller presents the way push and present, we first check whether it is presented. If so, we can find the present controller presented through this property, and then check whether it belongs to the UINavigationControler or UITabBarController. If so, look for the top layer in its child controller or the controller it is choosing. Finally, when determining whether the current controller has a sub-controller, if so, take the top layer of its sub-controller, otherwise the current controller is itself.

Here we mainly look for the view controllers managed by the current application based on UITabBarController and UINavigationController. If there are other controllers, you need to add if conditions to make judgments.

Method 2: When we have a view controller subView that is being rendered, we can recursively look up through the property nextResponder

+ (nullable UIViewController *)findBelongViewControllerForView:(UIView *)view {
  UIResponder *responder = view;
  while ((responder = [responder nextResponder]))
    if ([responder isKindOfClass: [UIViewController class]]) {
      return (UIViewController *)responder;
    }
  return nil;
}

presentedViewController

Apple Documentation presentedViewControlle

This method allows you to find the current controller introduced through the presented modal mode (display and hermit). For example: AViewController --> BViewController is launched modally. Then, you can get the BViewController by using it.

presentingViewController

Apple Documentation

This method can be used to find the upper controller that launches the current controller through the presented modal method (display and hermit). For example: AViewController --> BViewController is launched modally. Then, you can get the AViewController by using it.

modalViewController

After checking the document, I found that this method has been deprecated after iOS 6. The official recommendation is to use presentedViewController instead.

References and Dome

Dome: Easily get the current controller

The presentedViewController, presentingViewController and parentViewController three properties

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.