获取rootViewController的正确方式

最近项目中常常会出现,不一样的弹框同时出如今一个界面上的状况,因此研究了一下,如何避免此种状况的发生。app

(关于UIAlertView显示的问题可参考:https://www.jianshu.com/p/7ac398ef4532)ide

首先,获取rootViewController的方式有两种:测试

//方法一:
    UIWindow *windowW = [UIApplication sharedApplication].keyWindow;
    UIViewController *rootViewController1 = windowW.rootViewController;
    NSLog(@"rootViewController111 = %@",rootViewController1);

    //方法二:
    AppDelegate *appDele = (AppDelegate *)[UIApplication sharedApplication].delegate;
    UIViewController *rootViewController2 = appDele.window.rootViewController;
    NSLog(@"rootViewController222 = %@",rootViewController2);

这两种方法,通常状况下没有区别,可是有时候就会存在差别性,code

keyWindow属性:orm

 

UIAlertView的出现是由于,生成了一个新的window,加在了界面上面。这个时候获取到的keyWindow就是UIAlertControllerShimPresenterWindow。能够经过以下代码实验:blog

 

 

-(void)demo8{
    //获取rootViewController的两种方法,建议使用第二种
//    //方法一:
//    UIWindow *windowW = [UIApplication sharedApplication].keyWindow;
//    UIViewController *rootViewController1 = windowW.rootViewController;
//    NSLog(@"rootViewController111 = %@",rootViewController1);
//
//    //方法二:
//    AppDelegate *appDele = (AppDelegate *)[UIApplication sharedApplication].delegate;
//    UIViewController *rootViewController2 = appDele.window.rootViewController;
//    NSLog(@"rootViewController222 = %@",rootViewController2);
    
    UIButton *tempBtn = [UIButton buttonWithType:UIButtonTypeCustom];
    tempBtn.frame = CGRectMake(100, 100, 100, 100);
    [tempBtn setBackgroundColor:[UIColor cyanColor]];
    [tempBtn setTitle:@"输出结果" forState:UIControlStateNormal];
    [tempBtn addTarget:self action:@selector(tempBtnClick:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:tempBtn];
    
}
-(void)tempBtnClick:(UIButton *)btn{
    if ([[[UIDevice currentDevice] systemVersion] floatValue]>=9.0) {
        UIAlertController *alertC = [UIAlertController alertControllerWithTitle:@"测试RootViewController" message:@"测试测试" preferredStyle:UIAlertControllerStyleAlert];
        UIAlertAction *cancelA = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
        [alertC addAction:cancelA];
        [self presentViewController:alertC animated:YES completion:nil];
    }else{
        UIAlertView *alertV = [[UIAlertView alloc]initWithTitle:@"测试RootViewController" message:@"测试测试" delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:nil, nil];
        [alertV show];
    }
    
    //方法一:
    UIWindow *windowW1 = [UIApplication sharedApplication].keyWindow;

    //方法二:
    AppDelegate *appDele = (AppDelegate *)[UIApplication sharedApplication].delegate;
    UIWindow *windowW2 = appDele.window;
    
    //从输出的结果能够看出,若是用之前的UIAlertView弹窗,两种方式输出的结果不同,若是使用的UIAlertController弹窗,输出的结果同样,因此建议使用第二种方式进行rootViewController的获取
    NSLog(@"输出:\n 当前版本号为:%f \n window111 = %@   \n window222 = %@   \n window111.rootViewController = %@   \n window222.rootViewController = %@   \n",[[[UIDevice currentDevice] systemVersion] floatValue],windowW1,windowW2,windowW1.rootViewController,windowW2.rootViewController);
}

输出的结果:get

输出:
 当前版本号为:11.200000 
 window111 = <_UIAlertControllerShimPresenterWindow: 0x7fbde44194e0; frame = (0 0; 375 667); opaque = NO; gestureRecognizers = <NSArray: 0x604000446570>; layer = <UIWindowLayer: 0x604000034de0>>   
 window222 = <UIWindow: 0x7fbde440b780; frame = (0 0; 375 667); gestureRecognizers = <NSArray: 0x6040004417a0>; layer = <UIWindowLayer: 0x604000034860>>   
 window111.rootViewController = <UIApplicationRotationFollowingController: 0x7fbde44372f0>   
 window222.rootViewController = <UINavigationController: 0x7fbde4831a00>

结果明显不同,其实咱们通常状况下想获取的rootViewController是第二种,但愿咱们获取到在appdelegate中设置的appdelaget.window.rootViewController。it

因此了建议获取rootViewController的时候仍是采用:io

 

AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;class

UIViewController *rootViewController1 = appdelegate.window.rootViewController;

其实,和alertView相似的,UIActionSheet也是这样的。有时候若是不获取到正确的rootViewController,可能就会出现重叠或者视图处理不正确的问题,建议:即时经过第二种方法获取到了RootViewController,在使用以前建议再判断一下获取到的类是否是就是本身想要的类型,更保险一些。

AppDelegate *appdelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    if ([appdelegate.window.rootViewController isKindOfClass:["想要获取到的rootVC" class]] == YES) {
        
    }