最近项目中常常会出现,不一样的弹框同时出如今一个界面上的状况,因此研究了一下,如何避免此种状况的发生。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) { }