iOS 獲取當前正在顯示的視圖控制器ViewController(最全)

目錄

先插入以下介紹以下本編文章除標題所講知識外,還額外包含的內(nèi)容有如下:

1、獲取當前顯示的視圖控制器ViewController
2、如何在多次presentViewController后直接返回到指定層
3、presentedViewController 與 presentingViewController
4、如何通過視圖(view)獲取該視圖所在的控制器(viewController)

一、前言:

本來不怎么想寫這篇文章的, 因為這種東西網(wǎng)上隨便搜一大堆。但是還是發(fā)現(xiàn)項目中有些同學(xué),沒怎么理解好,直接照搬網(wǎng)上的,殊不知其本身雖處理了大部分情況,卻仍有一些情況是漏掉的。所以就有了下面這篇文章。

二、場景:

在處理 URL Router 跳轉(zhuǎn)的時候,經(jīng)常需要得到“當前最上層的視圖控制器”來進行視圖跳轉(zhuǎn)。

三、注意點:

網(wǎng)上比較多遺漏的場景是:A present B, B present C,在A中查找當前顯示的視圖控制器的情況。

四、直接快速使用方法:

使用方法很簡單:
①、Podfile添加pod 'CJBaseHelper/UIViewControllerCJHelper',并pod update或pod install
②、庫引入成功后,直接使用如下方法即可。即:

UIViewController *vc = [UIViewControllerCJHelper findCurrentShowingViewController];
或
UIViewController *vc = [UIViewControllerCJHelper findCurrentShowingViewControllerFrom:self];

至此,恭喜你大功告成?。?!


分割圖1.jpg

如果您還不清楚,可詳細查看以下說明。如果已清楚及不想了解原理,請?zhí)亮榭雌渌麅?nèi)容

詳細的使用方法及原理介紹如下:

1、查看開源庫CJBaseHelper內(nèi)容,可略過

獲取方法已整理到開源庫CJBaseHelper中的UIViewControllerCJHelper。該開源庫內(nèi)容,可通過pod search CJBaseHelper查看,查看結(jié)果如下:

CJBaseHelper/UIViewControllerCJHelper.png

如果你在終端執(zhí)行pod search CJBaseHelper,未得到上面的結(jié)果,是因為cocoaPods的本地search_index.json文件有問題,
方法①:請前往~/Library/Caches/CocoaPods/search_index.json將該文件刪除,
方法②:或者直接在終端輸入:rm ~/Library/Caches/CocoaPods/search_index.json,
刪除后,再重新執(zhí)行命令即可。

2、Podfile添加pod 'CJBaseHelper/UIViewControllerCJHelper'后,執(zhí)行pod install即可使用該庫中的UIViewControllerCJHelper,即。
platform :ios, '8.0'
inhibit_all_warnings!

target 'CJDemo' do
    pod 'CJBaseHelper', :subspecs => ['UIViewControllerCJHelper']
end

target 'CJDemoTests' do
    
end

即通過調(diào)用以下兩個方法中的任意一個即可獲取到當前顯示的視圖控制器。

///獲取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,參數(shù)vc為A時候的情況
/* 完整的描述請參見文件頭部 */
+ (UIViewController *)findCurrentShowingViewControllerFrom:(UIViewController *)vc
{
    //方法1:遞歸方法 Recursive method
    UIViewController *currentShowingVC;
    if ([vc presentedViewController]) { //注要優(yōu)先判斷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 {
        // 根視圖為非導(dǎo)航類
        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;
    //*/
}
分割圖1.jpg

六、其他補充:

2、如何在多次presentViewController后直接返回到指定層

場景:如果多個控制器都通過 present 的方式跳轉(zhuǎn)呢?比如從A跳轉(zhuǎn)到B,從B跳轉(zhuǎn)到C,從C跳轉(zhuǎn)到D,如何由D直接返回到A呢?

答:可以通過 presentingViewController 一直找到A控制器,然后調(diào)用A控制器的 dismissViewControllerAnimated 方法。方法如下:

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

PS:如果不是想直接返回到A控制器,比如想回到B控制器,while循環(huán)的終止條件可以通過控制器的類來判斷。

3、presentedViewController 與 presentingViewController

假設(shè)從A控制器通過present的方式跳轉(zhuǎn)到了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;
}

結(jié)束語:

如欲了解本文中更詳細內(nèi)容請點擊查看本文中所用開源庫CJBaseHelper中的UIViewControllerCJHelper。

=======================================================
其他更多好用的開源庫歡迎跳轉(zhuǎn)我的GitHub主頁,歡迎Watch/Star/Follow。
=======================================================

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容