UIWindow的概念與使用

UIWindow的作用
UIWindow是UIView的子類用於顯示程序內容。每一個UIView想要將內容顯示到屏幕上都需要依賴於一個UIWindow。
iOS應用程序要想正常運行至少要有一個UIWindow存在,通常這個UIWindow也就是應用程序的主窗口keyWindow。
APP中可以同時出現多個UIWindow,並且多個UIWindow之間是相互獨立的。它們可以同時出現,但只能有一個作爲keyWindow用來接收輸入事件,如文字輸入。
APP的事件傳遞鏈爲:應用程序收到事件之後會先轉發給keyWindow對象,然後keyWindow再將事件按照View的樹形結構遞歸轉發給view對象。

KeyWindow的作用
keyWindow是應用程序的關鍵Window,用來接收鍵盤以及非觸摸類的消息事件。雖然APP可能同時有多個UIWindow存在,但是程序中同一時刻只能有一個UIWindow是keyWindow。
這個也是是最後一個調用makeKeyAndVisible方法的UIWindow。

UIWindowScene 和 UIScene
UIScene表示應用程序中的一個場景的對象。一個場景通常對應於應用程序的一個界面或窗口,例如 iPad 上的分屏應用(一個APP,多場景)、iPhone 上的單個界面(一個APP,一個場景)。
每個 UIScene 可能包含一個或多個窗口 (UIWindow) 以及與之相關聯的視圖層次結構。
UIWindowScene 是 UIScene 的一個特殊子類,表示應用程序中的一個窗口場景。每個窗口場景都關聯一個或多個窗口,而每個窗口包含了應用程序的用戶界面。
所以在iOS中,每個UIWindow都要設置對應的UIWindowScene場景,當APP中同時出現多個UIWindow時,它們指向同一個正在活動的UIWindowScene場景。

makeKeyWindow與makeKeyAndVisible的區別
當新建一個UIWindow時,它的hideen屬性默認是YES的,既默認是不顯示的。
makeKeyWindow方法是將一個window設置爲keyWindow,如果window沒有變成keyWindow,則其內部的文本輸入框是沒法輸入文字的,既無法接收輸入事件。

makeKeyAndVisible方法會將一個window設置爲keyWindow,並且將其hideen設置爲NO,顯示出來。
makeKeyAndVisible之後,系統對window做的事情如下:
1.將UIApplication對象的keyWindow設置爲當前這個window
2.當前window的hidden設置爲NO,同時該window的keyWindow屬性變爲YES

UIWindow的主要屬性
@property(nonatomic,strong) UIScreen *screen

一個UIScreen對象對應一個實際設備的物理屏幕,該屬性默認爲[UIScreen mainScreen]。一個iPhone默認一個屏幕,而一個屏幕可以存在多個window,這也是APP中可以同時存在多個window的原因。


@property(nullable, nonatomic,strong) UIViewController *rootViewController;

該屬性爲window的根控制器,這個屬性是不能爲空的,必須進行賦值


@property(nullable, nonatomic, weak) UIWindowScene *windowScene API_AVAILABLE(ios(13.0)

ios13以上必須設置windowScene屬性,否則window不顯示


- (CGPoint)convertPoint:(CGPoint)point toWindow:(nullable UIWindow *)window;
- (CGPoint)convertPoint:(CGPoint)point fromWindow:(nullable UIWindow *)window;
- (CGRect)convertRect:(CGRect)rect toWindow:(nullable UIWindow *)window;
- (CGRect)convertRect:(CGRect)rect fromWindow:(nullable UIWindow *)window;

window之間是相互獨立的,如果想要將兩個window的座標相互映射的時候,就需要用到以上幾個方法。


UIWindow的創建步驟
1.創建一個window對象,並用一個對象強持有它
2.創建一個控制器,賦值爲window的根控制器
3.設置當前活動的windowScene對象
4.顯示窗口
//1. 創建一個window對象,並用一個對象強持有它
//UIWindow的大小是通過frame自定義設置的,frame決定了這個窗口大小
UIWindow *testWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
testWindow.windowLevel = UIWindowLevelStatusBar;
self.testWindow = testWindow;
//2. 創建一個控制器,賦值爲window的根控制器
UIViewController *controller = [[UIViewController alloc] init];
testWindow.rootViewController = controller;
//3.設置當前活動的windowScene對象
for (UIWindowScene *windowScene in [UIApplication sharedApplication].connectedScenes) {
    if (windowScene.activationState == UISceneActivationStateForegroundActive) {
        self.alertWindow.windowScene = windowScene;
        break;
    }
}
//4. 顯示窗口
[testWindow makeKeyAndVisible];
系統window等級
UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal; 0
UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert; 2000
UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar; 4000

 

如何銷燬一個 UIWindow
將window的hidden屬性置爲YES
將持有該window的那個對象對window的持有去掉
self.testWindow.hidden = YES;
self.testWindow = nil;

 

參考文章:
https://www.jianshu.com/p/98cd7fc4bfba
 
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章