多页面悬停控件和如何获得多UIWindow的页面UIWindow

若你的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] (
    "",
    ""
)

当然判断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];`。

你可能感兴趣的:(ios)