一. 關于UIWindow
- UIWindow是一種特殊的UIView坝初,通常在一個app中只會有一個UIWindow身害。
- iOS程序啟動完畢后感昼,創(chuàng)建的第一個視圖控件就是UIWindow荷憋,接著創(chuàng)建控制器,再創(chuàng)建控制器的view承绸,最后將控制器的view添加到UIWindow上裸影,于是控制器的view就顯示在屏幕上了。
- 一個iOS程序之所以能顯示到屏幕上军熏,完全是因為它有UIWindow轩猩,也就是說,沒有UIWindow,就看不見任何UI界面均践。
- UIWindow是創(chuàng)建的第一個視圖控件晤锹,UIapplication是創(chuàng)建的第一個對象。
文檔中關于該部分的解釋:
二. UIWindow的使用
1. 創(chuàng)建window
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
2. 把view添加到window上
創(chuàng)建一個控制器彤委,把view添加到window上面鞭铆,有兩種方式:
方式1:
直接將控制器的view添加到window中,并不理會它對應的控制器
[self.window addsubview:vc.view];
方式2:推薦
設置window的根控制器葫慎,自動將rootviewcontroller的view添加到window中衔彻,負責管理rootviewcontroller的生命周期(推薦這種方式)。
[self.window.rootviewcontroller = vc];
方式1的問題:
問題1:當view發(fā)生一些事件的時候偷办,通知控制器艰额,但是控制器已經(jīng)銷毀了,所以可能出現(xiàn)未知的錯誤椒涯。比如說控制器上面可能有按鈕柄沮,需要監(jiān)聽按鈕的點擊事件,如果是1废岂,那么按鈕的事件應該由控制器來進行管理祖搓,但控制器是一個局部變量,控制器此時已經(jīng)不存在了湖苞,但是控制器的view還在拯欧,此時有可能會報錯。
問題2:添加一個開關按鈕财骨,讓屏幕360度旋轉镐作,當發(fā)生屏幕旋轉事件的時候,UIapplication對象會將旋轉事件傳遞給window隆箩,window又會將旋轉事件傳遞給它的根控制器该贾,由根控制器決定是否需要旋轉,如下:
UIapplication->UIWindow->根控制器捌臊,由于第一種方式?jīng)]有根控制器杨蛋,所以不能跟著旋轉。
三. UIWindow的創(chuàng)建過程
1. 有storyboard
- 為什么創(chuàng)建一個storyboard理澎,沒有看到創(chuàng)建window的過程逞力?
它其實是把創(chuàng)建UIWindow的過程給屏蔽起來了】放溃可以把代理的UIWindow的屬性的值打印出來:
NSLog(@“window=%p”,self.window);
打印出來確實是有值的掏击,說明確實創(chuàng)建了UIWindow,不僅創(chuàng)建了UIWindow秩铆,默認還創(chuàng)建了UIWindow對應的控制器砚亭,也可以打印進行查看灯变。
NSLog(@“%@“,self.window.rootviewcontroller);
- 有storyboard的項目中的創(chuàng)建過程:
當用戶點擊應用程序圖標的時候,先執(zhí)行Main函數(shù)捅膘,執(zhí)行UIApplicationMain(),根據(jù)其第三個和第四個參數(shù)創(chuàng)建Application添祸,創(chuàng)建代理,并且把代理設置給application寻仗,然后查看項目配置文件info.plist里面的storyboard的name刃泌,根據(jù)這個name找到對應的storyboard,開啟一個事件循環(huán)署尤,當程序加載完畢耙替,他會調用代理的didFinishLaunchingWithOptions:方法。在調用didFinishLaunchingWithOptions:方法之前曹体,會加載storyboard俗扇,在加載的時候創(chuàng)建一個window,接下來會創(chuàng)建箭頭所指向的控制器箕别,把該控制器設置為UIWindow的根控制器铜幽,接下來再將window顯示出來,即看到了運行后顯示的界面串稀。關于這部分可以查看story的初始化的文檔:
2. 沒有storyboard
先執(zhí)行Main函數(shù)除抛,執(zhí)行UIApplicationMain(),根據(jù)其第三個和第四個參數(shù)創(chuàng)建Application,創(chuàng)建代理母截,并且把代理設置給application到忽,開啟一個事件循環(huán),當程序加載完畢清寇,他會調用代理的didFinishLaunchingWithOptions:方法喘漏。在該方法中,會創(chuàng)建一個Window,然后創(chuàng)建一個控制器颗管,并把該控制器設置為UIWindow的根控制器,接下來再將window顯示出來滓走,即看到了運行后顯示的界面垦江。
四. 主窗口
1. 設置主窗口
[self.window makekeyandvisible]
讓窗口成為主窗口,并且顯示出來搅方。有這個方法比吭,才能把信息顯示到屏幕上。
因為window有makekeyandvisible這個方法姨涡,可以讓這個window憑空的顯示出來衩藤,而其他的view沒有這個方法,所以它只能依賴于window涛漂,window顯示出來后赏表,view才依附在window上顯示出來检诗。
一個應用程序中只能有一個主窗口,如果程序中設置了兩個主窗口瓢剿,后面的主窗口能覆蓋前面的主窗口逢慌。
[self.window make keywindow]
讓window成為主窗口,但不顯示间狂。
2. 獲取window
[UIApplication sharedApplication].windows;
在本應用中打開的UIWindow列表攻泼,這樣就可以獲取應用中的任何一個UIView對象,平時輸入文字彈出的鍵盤鉴象,就處在一個新的UIWindow中忙菠。
[UIApplication sharedApplication].keyWindow;
獲取應用程序的主窗口,而且程序中每個時刻只能有一個window是keyWindow纺弊。
UIWindow *viewWindow = view.window;
獲得某個UIView所在的UIWindow牛欢。
五. UIWindow的用處
在IOS應用中,我們使用UIWindow和UIView來呈現(xiàn)界面俭尖。UIWindow并不包含任何默認的內容氢惋,它被當做UIView的容器,用于放置應用中所有的UIView稽犁。從繼承關系來看焰望,UIWindow繼承自UIView,所以UIWIndow除了具有UIView的所有功能外已亥,還增加了一些特有的屬性和方法熊赖。
UIWindow的主要作用:
- 作為UIView的最頂層容器,包含應用顯示所需要的所有UIView
- 傳遞觸摸消息和鍵盤事件給UIView
關于系統(tǒng)對UIWindow的使用:
通常在一個程序中只會有一個UIWindow虑椎,但有些時候我們調用系統(tǒng)的控件(例如UIAlertView)時震鹉,IOS系統(tǒng)為了保證UIAlertView在所有的界面之上,它會臨時創(chuàng)建一個新的UIWindow捆姜,通過將其UIWindow的UIWindowLevel設置的更高传趾,讓UIWindow蓋在所有的應用界面之上(熟悉html的朋友應該知道,網(wǎng)頁上面的“遮罩效果”泥技,就是通過設置元素的z-index屬性浆兰,來控制層級的上下關系,是一個道理)珊豹。