获取当前的ViewController

获取当前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)