background
During development, you often need to get the requirements for the current Window, rootViewController, and visibleController that is currently being displayed. If the.m implementation is not in the current view, and we need to get the current controller quickly, then we need to do a layer of encapsulation. I usually write a Category on UIViewController, and it’s very easy to implement, 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 window.rootViewController;
}
Copy the code
It’s easy to get the delegate of the current UIApplication singleton and then get the rootViewController from the window.
Gets the current page controller
+ (UIViewController *)jsd_findVisibleViewController {
UIViewController* currentViewController = [self jsd_rootViewController];
BOOL runLoopFind = YES;
while (runLoopFind) {
if(currentViewController.presentedViewController) { currentViewController = currentViewController.presentedViewController; }else {
if ([currentViewController isKindOfClass:[UINavigationController class]]) {
currentViewController = ((UINavigationController *)currentViewController).visibleViewController;
} else if ([currentViewController isKindOfClass:[UITabBarController class]]) {
currentViewController = ((UITabBarController* )currentViewController).selectedViewController;
} else {
break; }}}return currentViewController;
}
Copy the code
Here is the implementation idea. If we want to obtain the current controller directly without coupling with the controller, we basically use rootViewController to find the controller. After obtaining rootViewControoler, we use the above method. So we’re going to look at presentedViewController, because the controller presents push and present, and we’re going to see if it’s presented, and if it is, we’re going to use this property to find the current controller that’s presented, Then check whether it belongs to the UINavigationControler or UITabBarController, if so, by looking for the topmost controller in its child controller or the controller it is selecting. Finally, judge whether the current controller has a child controller, if so, take the top layer of the child controller, otherwise the current controller is itself.
Find the view controllers managed by the current application under UITabBarController and UINavigationControler. If there are other controllers, add an IF condition.
Method 2: When we have a View controller child View that is being rendered, we can recursively find it with 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;
}
Copy the code
presentedViewController
Apple document presentedViewControlle
This method allows you to find the current controller that was presented in the Presented mode mode (Show and Hermit). For example: AViewController –> BViewController is modally derived. Use AViewController. PresentedViewController to BViewController it can get.
presentingViewController
Apple document
This method allows you to find the upper-layer controller that presented the current controller in an Elegant mode (Show and Hermit). For example: AViewController –> BViewController is modally derived. Use BViewController. PresentingViewController to AViewController it can get.
modalViewController
This method has been deprecated since iOS 6. The official recommendation is to use presentedViewController instead.
References and Dome
UIViewController’s presentedViewController, presentingViewController, and parentViewController properties Dome: Easily retrieve the current controller
I hope this article is helpful to you. If there is something wrong, I hope you can leave a message to correct it. Thank you !!!!! Study on the way, with you!!