多頁面懸停控件和如何獲得多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] (
    "<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];`。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章