你真的瞭解UIWindow嗎?,UIWindow
一:首先查看一下關於UIWindow的定義
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIWindow : UIView//window的螢幕,預設是 [UIScreen mainScreen] ,不能更改,否則沒有介面@property(nonatomic,strong) UIScreen *screen NS_AVAILABLE_IOS(3_2); //window的視圖層級,預設是0.0@property(nonatomic) UIWindowLevel windowLevel; //是否是keyWindow@property(nonatomic,readonly,getter=isKeyWindow) BOOL keyWindow;//該方法不應該被手動調用,當window變為keyWindow時會被自動調用來通知window。可以繼承UIWindow重寫此方法來實現功能- (void)becomeKeyWindow; // 該方法不應該被手動調用,當window不再是keyWindow時(例如其他window執行個體調用了- makeKeyWindow或- makeKeyAndVisible方法)會被自動調用來通知window。可以繼承UIWindow重寫此方法來實現功能。 - (void)resignKeyWindow; //該方法使window變為keyWindow,但不影響顯示狀態- (void)makeKeyWindow;//顯示主window並將window設為key並顯示,該方法讓window顯示並變為keyWindow。調用該方法會讓window排在其level組中的最上面。如果只想改變window的顯示而不影響keyWindow狀態,可以直接設定window的hidden屬性為NO。- (void)makeKeyAndVisible; //根控制器@property(nullable, nonatomic,strong) UIViewController *rootViewController NS_AVAILABLE_IOS(4_0); //UIApplication調用window的該方法給window分發事件,window再將事件分發到合適的目標,比如將觸摸事件分發到真正觸摸的view上。可以直接調用該方法分發自訂事件。- (void)sendEvent:(UIEvent *)event; // 把該window中的一個座標轉換成在目標window中時的座標值- (CGPoint)convertPoint:(CGPoint)point toWindow:(nullable UIWindow *)window; // 把目標window中的一個座標轉換成在該window中時的座標值- (CGPoint)convertPoint:(CGPoint)point fromWindow:(nullable UIWindow *)window; // 把該window中的一個矩陣轉換成在目標window中時的矩陣值- (CGRect)convertRect:(CGRect)rect toWindow:(nullable UIWindow *)window;// 把目標window中的一個矩陣轉換成在該window中時的矩陣值- (CGRect)convertRect:(CGRect)rect fromWindow:(nullable UIWindow *)window;@end
UIWindow是一種特殊的UIView,通常在一個app中至少會有一個UIWindow。iOS程式啟動完畢後,建立的第一個視圖控制項就是UIWindow,接著建立控制器的View,最後將控制器的View添加到UIWindow上,於是控制器的View就顯示在螢幕上了。一個iOS程式之所以能顯示在螢幕上,完全是因為它有UIWindow,也就是說,沒有UIWindow就看不到任何UI介面。狀態列和鍵盤都是特殊的UIWindow;UIWindow還是事件處理的重要組成部分,當應用最初收到事件時,會派發給合適的UIWindow對象,再由其傳遞到合適的UIView對象。同時,window和view controller對象一起工作還可以實現介面旋轉等其他控制操作。
知識點1:UIWindowLevel常量值 設定UIWindow的等級
UIKIT_EXTERN const UIWindowLevel UIWindowLevelNormal; //預設,值為0UIKIT_EXTERN const UIWindowLevel UIWindowLevelAlert; //值為2000 UIKIT_EXTERN const UIWindowLevel UIWindowLevelStatusBar ; // 值為1000
該屬性工作表示了window在螢幕z軸方向上的位置,系統提供了UIWindowLevel的三個常量值,顯示應用內容的main window預設設定為UIWindowLevelNormal,即最低的level。其他一些介面元素比如status bar和alert view會使用相應的level。windowLevel也可以設定為其他的任意數值,比如系統鍵盤所在的window,其windowLevel總是比調用鍵盤的window的level大1,選中輸入內容時的拷貝,粘貼等選項所在的window其windowLevel是2100。可以多個window設定為同一個windowLevel,在這些window中,最後調用顯示方法的window排在上面。不同level的window組中,總是更高level的window在低level的window的上面。
知識點2:監測window的通知:
UIKIT_EXTERN NSString *const UIWindowDidBecomeVisibleNotification; // 當window啟用時並展示在介面的時候觸發,返回空UIKIT_EXTERN NSString *const UIWindowDidBecomeHiddenNotification; // 當window隱藏的時候觸發,暫時沒有實際測,返回空UIKIT_EXTERN NSString *const UIWindowDidBecomeKeyNotification; // 當window被設定為keyWindow時觸發,返回空UIKIT_EXTERN NSString *const UIWindowDidResignKeyNotification; // 當window的key位置被取代時觸發,返回空
知識點3:代碼來建立window初始化介面
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; myViewController = [[MyViewController alloc] init]; window.rootViewController = myViewController; [window makeKeyAndVisible]; return YES;}
知識點4:在有storyboard的項目中,UIWindow是如何建立的?
當使用者點擊應用程式圖示的時候,先執行Main函數,執行UIApplicationMain(),根據其第三個和第四個參數建立Application,建立代理,並且把代理設定給application(看項目設定檔info.plist裡面的storyboard的name,根據這個name找到對應的storyboard),開啟一個事件迴圈,當程式載入完畢,他會調用代理的didFinishLaunchingWithOptions:方法。在調用didFinishLaunchingWithOptions:方法之前,會載入storyboard,在載入的時候建立一個window,接下來會建立箭頭所指向的控制器,把該控制器設定為UIWindow的根控制器,接下來再將window顯示出來,即看到了運行後顯示的介面。
知點點5:擷取UIwindow
1:[UIApplication sharedApplication].windows在本應用中開啟的UIWindow列表,這樣就可以接觸應用中的任何一個UIView對象(平時輸入文字彈出的鍵盤,就處在一個新的UIWindow中)。
2:[UIApplication sharedApplication].keyWindow(擷取應用程式的主視窗)用來接收鍵盤以及非觸摸類的訊息事件的UIWindow,而且程式中每個時刻只能有一個UIWindow是keyWindow。
提示:如果某個UIWindow內部的文字框不能輸入文字,可能是因為這個UIWindow不是keyWindow。
3:view.window獲得某個UIView所在的UIWindow。