若你的app需要悬停一个控件在绝大多数页面上,那么最后的解决方案是:把这个控件做成一个UIWindow,并且设置_statusWindow.windowLevel = UIWindowLevelStatusBar + 1;。注意:这个控件是显示在所有页面中的,除非页面掉用了它的隐藏函数([[PPPlayNoticeView currentNotice] animationHide];),不然它在app那个页面都显示。不过它依赖于app(app就是一个单进程应用,不可能存在多个进程。WKWebView是我见到的iOS唯一一个进程组件,不过通过它起的进程在iOS操作系统中,它虽然和app有通信机制,收到那个进程的数据,但是不受app管辖,app收到它的数据也可能是不实时的,像cookie数据),不会显示在其它app页面中,这个安卓是不一样的。UIAlertView弹窗是系统级别的,可以不依赖于app存在,但是它出来后,不让它消失什么也干不了。不是我们需要控件。
那新问题来了,若这个跨页面的控件显示时,你使用在keywindow上增加图层,可能时增加到这个控件UIWindow的keywindow上。结果是你那个图层显示不出来,只看到一个带透明度的图层。那如何找到当前页面的UIWindow呢?使用下面函数就能找到。
-(UIWindow *)getLevelNormalWindwow { NSArray *windows = [[UIApplication sharedApplication] windows]; for(UIWindow * tmpWin in windows) { if (tmpWin.windowLevel == UIWindowLevelNormal) { UIViewController *result = nil; UIView *frontView = [[tmpWin subviews] objectAtSafeIndex:0]; id nextResponder = [frontView nextResponder]; if ([nextResponder isKindOfClass:[UIViewController class]]) result = nextResponder; else result = tmpWin.rootViewController; NSArray *cv = [result childViewControllers]; NSLog(@"%@",cv); if(cv && [cv isKindOfClass:[NSArray class]] && cv.count > 0) { return tmpWin; } } } return nil; }
日志打印:
2020-06-18 13:47:08.898734+0800 PinkPig[5900:133486] ( "<BITBaseTabBarController: 0x7fafb2e154e0>", "<PPRoomViewController: 0x7fafb4816800>" )
当然判断if (tmpWin.windowLevel == UIWindowLevelNormal)就够了,下面多的if(cv && [cv isKindOfClass:[NSArray class]] && cv.count > 0)只是以防万一。你新建的UIWindow不会是UIWindowLevelNormal,不然不知道那个页面在上面呢!,当然你建立rootViewController所在的window时,设置了非UIWindowLevelNormal的值那个判断也要变成你设置成的windowLevel值(就是修改这句if (tmpWin.windowLevel == UIWindowLevelNormal)),不设置windowLevel是默认值UIWindowLevelNormal。
一般是在AppDelegate里设置UIWindow的,如:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:LoginVC]; self.window.rootViewController = nav; [self.window makeKeyAndVisible]; ```。 当然我采用的组件化,是在系统模块里设置self.tabBarController的。 具体使用代码:
[self addSubview:self.headDetailView];
当然你可以把这个函数放在静态类或单例中,在那里都能调用该函数,如在调用单例的该函数`[[[UIApplication sharedApplication] keyWindow] addSubview:self.headDetailView];`。