iOS 获取当前正在显示的视图控制器ViewController(最全)

作者 : 开心源码 本文共5043个字,预计阅读时间需要13分钟 发布时间: 2022-05-12 共194人阅读

目录

先插入以下详情以下本编文章除标题所讲知识外,还额外包含的内容有如下:

1、获取当前显示的视图控制器ViewController
2、如何在屡次presentViewController后直接返回到指定层
3、presentedViewController 与 presentingViewController
4、如何通过视图(view)获取该视图所在的控制器(viewController)

一、前言:

原本不怎样想写这篇文章的, 由于这种东西网上随意搜一大堆。但是还是发现项目中有些同学,没怎样了解好,直接照搬网上的,殊不知其本身虽解决了大部分情况,却仍有少量情况是漏掉的。所以就有了下面这篇文章。

二、场景:

在解决 URL Router 跳转的时候,经常需要得到“当前最上层的视图控制器”来进行视图跳转。

三、注意点:

网上比较多遗漏的场景是:A present B, B present C,在A中查找当前显示的视图控制器的情况。

四、直接快速使用方法:

使用方法很简单:
①、Podfile增加pod 'CJBaseHelper/UIViewControllerCJHelper',并pod update或者pod install
②、库引入成功后,直接使用UIViewControllerCJHelper类中的findCurrentShowingViewController或者findCurrentShowingViewControllerFrom:方法就可。如:

UIViewController *vc = nil;

vc = [UIViewControllerCJHelper findCurrentShowingViewController];
或者
vc = [UIViewControllerCJHelper findCurrentShowingViewControllerFrom:self];

假如您还不清楚,可详细查看以下说明。假如已清楚及不想理解原理,请跳至六查看其余内容

详细的使用方法及原理详情如下:

1、查看开源库CJBaseHelper内容,可略过

获取方法已整理到开源库CJBaseHelper中的UIViewControllerCJHelper。该开源库内容,可通过pod search CJBaseHelper查看,查看结果如下:

CJBaseHelper/UIViewControllerCJHelper.png
假如你在终端执行pod search CJBaseHelper,未得到上面的结果,是由于cocoaPods的本地search_index.json文件有问题,
方法①:请前往~/Library/Caches/CocoaPods/search_index.json将该文件删除,
方法②:或者者直接在终端输入:rm ~/Library/Caches/CocoaPods/search_index.json
删除后,再重新执行命令就可。

2、Podfile增加pod 'CJBaseHelper/UIViewControllerCJHelper'后,执行pod install即用该库中的UIViewControllerCJHelper,即。
platform :ios, '8.0'inhibit_all_warnings!target 'CJDemo' do    pod 'CJBaseHelper', :subspecs => ['UIViewControllerCJHelper']endtarget 'CJDemoTests' do    end

即通过调用以下两个方法中的任意一个就可获取到当前显示的视图控制器。

///获取Window当前显示的视图控制器ViewController+ (UIViewController *)findCurrentShowingViewController;/** *  获取Window当前显示的视图控制器ViewController * *  @param vc   从哪个界面开始分析 * *  @return 当前显示的视图控制器ViewController */+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc;
3、实际使用过程
    //获取Window当前显示的视图控制器ViewController方法①    UIViewController *currentShowViewController1 = [UIViewControllerCJHelper findCurrentShowingViewController];    NSLog(@"currentShowViewController1 = %@", NSStringFromClass([currentShowViewController1 class]));        //获取Window当前显示的视图控制器ViewController方法②    UIViewController *currentShowViewController2 = [UIViewControllerCJHelper findCurrentShowingViewControllerFrom:self];    NSLog(@"currentShowViewController2 = %@", NSStringFromClass([currentShowViewController2 class]));

五、上述使用的CJBaseHelper/UIViewControllerCJHelper库的代码解析

代码中包括两种方法,一种是遍历方法,一种是递归方法,两种方法都能正确查找到当前正在显示的视图控制器。废话不多说,直接上代码。

+ (UIViewController *)findCurrentShowingViewController {    //取得当前活动窗口的根视图    UIViewController *vc = [UIApplication sharedApplication].keyWindow.rootViewController;    UIViewController *currentShowingVC = [self findCurrentShowingViewControllerFrom:vc];    return currentShowingVC;}//注意考虑几种特殊情况:①A present B, B present C,参数vc为A时候的情况/* 完整的形容请参见文件头部 */+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc{    //方法1:递归方法 Recursive method    UIViewController *currentShowingVC;    if ([vc presentedViewController]) { //注要优先判断vc能否有弹出其余视图,如有则当前显示的视图一定是在那上面        // 当前视图是被presented出来的        UIViewController *nextRootVC = [vc presentedViewController];        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];            } else if ([vc isKindOfClass:[UITabBarController class]]) {        // 根视图为UITabBarController        UIViewController *nextRootVC = [(UITabBarController *)vc selectedViewController];        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];            } else if ([vc isKindOfClass:[UINavigationController class]]){        // 根视图为UINavigationController        UIViewController *nextRootVC = [(UINavigationController *)vc visibleViewController];        currentShowingVC = [self findCurrentShowingViewControllerFrom:nextRootVC];            } else {        // 根视图为非导航类        currentShowingVC = vc;    }        return currentShowingVC;        /*    //方法2:遍历方法    while (1)    {        if (vc.presentedViewController) {            vc = vc.presentedViewController;                    } else if ([vc isKindOfClass:[UITabBarController class]]) {            vc = ((UITabBarController*)vc).selectedViewController;                    } else if ([vc isKindOfClass:[UINavigationController class]]) {            vc = ((UINavigationController*)vc).visibleViewController;                    //} else if (vc.childViewControllers.count > 0) {        //    //假如是普通控制器,找childViewControllers最后一个        //    vc = [vc.childViewControllers lastObject];        } else {            break;        }    }    return vc;    //*/}

六、其余补充:

2、如何在屡次presentViewController后直接返回到指定层

场景:假如多个控制器都通过 present 的方式跳转呢?比方从A跳转到B,从B跳转到C,从C跳转到D,如何由D直接返回到A呢?

答:可以通过 presentingViewController 一直找到A控制器,而后调用A控制器的 dismissViewControllerAnimated 方法。方法如下:

UIViewController *controller = self;while(controller.presentingViewController != nil){    controller = controller.presentingViewController;}[controller dismissViewControllerAnimated:YES completion:nil];

PS:假如不是想直接返回到A控制器,比方想回到B控制器,while循环的终止条件可以通过控制器的类来判断。

3、presentedViewController 与 presentingViewController

假设从A控制器通过present的方式跳转到了B控制器,那么 A.presentedViewController 就是B控制器;
B.presentingViewController 就是A控制器。

4、如何通过视图(view)获取该视图所在的控制器(viewController)

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

结束语:

如欲理解本文中更详细内容请点击查看本文中所用开源库CJBaseHelper中的UIViewControllerCJHelper

=======================================================
其余更多好用的开源库欢迎跳转我的GitHub主页,欢迎Watch/Star/Follow。
=======================================================

说明
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » iOS 获取当前正在显示的视图控制器ViewController(最全)

发表回复