最近在封裝一個HUD彈窗,要獲取最上層可以顯示的window,所以研究了一下,發(fā)覺現(xiàn)在網(wǎng)上關于iOS11之后的變化,大家解釋的都不是很清楚,我這里說一下我的處理方法,也解釋一下原因。
之前大家獲取最上層window的方法:
let window = UIApplication.shared.windows.last!
這個方法iOS11之后,經(jīng)常會出現(xiàn)添加上去的視圖不顯示的問題,于是大家有的就用下面這個方法??:
let window = UIApplication.shared.keyWindow!
可是你要知道,這個方法拿到的是keyWindow
,一般是我們在AppDelegate
里面我們創(chuàng)建的用于顯示的window,很多情況下不是最上層的,比如有鍵盤正在輸入的時候,鍵盤的window是在keyWindow上層的,所以你添加的hud彈窗等會被鍵盤擋住!
我們來看一下鍵盤顯示的時候的window的層級關系:
image.png
image.png
- UIWindow 這個就是我們自己創(chuàng)建顯示視圖的keyWindow
- UITextEffectsWindow iOS8新增,鍵盤所在的window
-
UIRemoteKeyboardWindow iOS9新增,顯示鍵盤視圖的window
我們可以看到鍵盤顯示的時候,iOS9之后UIApplication.shared.windows.last!
是我們顯示鍵盤的UIRemoteKeyboardWindow
,這個window會在鍵盤隱藏之后就銷毀,所以在鍵盤隱藏的瞬間,如果在上面添加視圖,就會閃一下,或者不顯示,就是因為這個window在鍵盤隱藏之后就移除銷毀了
劃重點,我來說一種我遇到超級坑的情況:iOS11之后,如果你使用UIImagePickerController
獲取相冊或者打開相機,系統(tǒng)也會自動創(chuàng)建一個UIRemoteKeyboardWindow
,雖然這個window的isHidden
等顯示屬性都是打開的,但是添加在上面的視圖就是不顯示,而且它一直霸占在windows的last位置還不釋放,所以就出現(xiàn)了你取last添加視圖,怎么也不顯示的情況了
也就是說,當鍵盤顯示的時候,last的UIRemoteKeyboardWindow
是可以添加我們的hud等視圖,并顯示出來,但是當鍵盤隱藏,last的UIRemoteKeyboardWindow
是不可以做顯示的,我們看一下我獲取最上層可顯示window的方法:??
func frontWindow() -> UIWindow? {
for window in UIApplication.shared.windows.reversed() {
guard window.screen == UIScreen.main else {
continue
}
guard !window.isHidden && window.alpha > 0 else {
continue
}
guard window.windowLevel >= .normal else {
continue
}
guard !window.description.hasPrefix("<UIRemoteKeyboardWindow") || IQKeyboardManager.shared.keyboardShowing else {
continue
}
return window
}
return nil
}
我比較喜歡使用guard
的語法糖,逆序遍歷windows,前面的三個判斷是排除了不作顯示的window,然后最后一個判斷就是如果是UIRemoteKeyboardWindow
,在鍵盤不顯示的情況下,我們不使用它,繼續(xù)挑選它下層的window
IQKeyboardManager
是我用來判斷當前鍵盤狀態(tài)的工具類(這個第三方很強大,兩句代碼就可以幫助你處理所有鍵盤遮擋輸入框的情況)
我這里是對鍵盤的window做了單獨判斷,來確保它可以顯示,如果你有其他的更方便的方法歡迎討論
這樣獲取到的window就可以讓我們的hud顯示在包括鍵盤在內(nèi)的最上層,不會被遮擋
歡迎更正錯誤和交流,回復評論和私信皆可 ??