美文网首页
获取当前的ViewController

获取当前的ViewController

作者: 好个秋先生 | 来源:发表于2016-09-11 15:51 被阅读303次

    获取当前UIViewController获取当前的UIViewController有很多好处,比如找到当前代理、通知对象,添加Subview达到提示框和弹出框的效果等。

    要获取到当前UIViewController对象,首先我们需要了解界面的层级关系。在界面最底层的是一个UIWindow,也是唯一的keywindow,负责将当前UIControlView的View加载到UIWindow上,也就是mainView。其它的subView再加在到mainView上。最后形成我们所看到的界面。

    UIWindowLevel UIWindow有三个层级,分别是Normal,StatusBar,Alert。三个层级的值从左到右依次是0,1000,2000,也就是说Normal级别是最低的,StatusBar处于中等水平,Alert级别最高。 而通常我们的程序的界面都是处于Normal这个级别上的,系统顶部的状态栏应该是处于StatusBar级别,UIActionSheet和UIAlertView这些通常都是用来中断正常流程,提醒用户等操作,因此位于Alert级别。window显示级别优先的原则,级别高的会显示在上面,级别低的在下面,我们程序正常显示的view位于最底层。 每一个UIApplication 只有一个keyWindow,也就是最底层级别为UIWindowLevelNormal的Window。

    UIResponder(响应者)

    响应者对象(Responder Object),顾名思义,指的是有响应和处理事件能力的对象。响应者链就是由一系列的响应者对象构成的一个层次结构。 UIResponder是所有响应对象的基类,在UIResponder类中定义了处理上述各种事件的接口。我们熟悉的UIApplication、 UIViewController、UIWindow和所有继承自UIView的UIKit类都直接或间接的继承自UIResponder,所以它们的实例都是可以构成响应者链的响应者对象。

    举个栗子:

    我用SingleView模板创建了一个新的工程,它的主Window上只有一个UIViewController,其View之上有一个subview。响应者链如下: subview-->UIView-->UIViewController-->UIWindow-->UIapplication-->AppDelegate获取current ViewController得到 keyWindow,以windowLevel==UIWindowLevelNormal为条件得到KeyWindow上的subview[0]判断subview[0]的nextResponder是否是UIViewController类,是则为CurrentViewController,否则当前控制器为keyWindow.rootViewController

      - (UIViewController *)currentController { 
        UIViewController *result = nil;
       UIWindow *window = [[UIApplication sharedApplication] keyWindow]; 
       if (window.windowLevel != UIWindowLevelNormal) { 
    
         NSArray *windows = [[UIApplication sharedApplication] windows]; 
         for (UIWindow *temWin in windows) {
              if (temWin.windowLevel == UIWindowLevelNormal) {
                   window = temWin;
                   break;
               }
          }
       }
    
        UIView *frontView = [[window subviews] objectAtIndex:0];
        id nestResponder = [frontView nextResponder];
         if ([nestResponder isKindOfClass:[UIViewController class]]) {
              result = nestResponder; } else {
              result = window.rootViewController;
        } 
        return result;
    }
    

    但当存在模态退出控制器是,如采用presentViewController:animated:completion:,这时通过上面的方法是找不到presentViewController 的。需要每次拿到 currentController再判断是否有controller被模态推出:

    UIViewController *VC = [self curController];
        if (VC.presentedViewController) {
            //此时为VC.presentedViewController
        }else{
            //为VC
        }
    

    相关文章

      网友评论

          本文标题:获取当前的ViewController

          本文链接:https://www.haomeiwen.com/subject/hfyxettx.html