一、簡單介紹
uiwindow是一種特殊的uiview,通常在一個app中隻會有一個uiwindow
ios程式啟動完畢後,建立的第一個視圖控件就是uiwindow,接着建立控制器的view,最後将控制器的view添加到uiwindow上,于是控制器的view就顯示在螢幕上了
一個ios程式之是以能顯示到螢幕上,完全是因為它有uiwindow。也就說,沒有uiwindow,就看不見任何ui界面
補充:uiwindow是建立的第一個視圖控件(建立的第一個對象是uiapplication)如下圖:

添加
先建立uiwindow,再建立控制器,建立控制器的view,然後将控制器的view添加到uiwindow上。
文檔中關于該部分的解釋:
二、uiwindow的建立過程
1.簡單說明
建立一個空的項目,就可以看到uiwindow是怎麼出來的了。在程式啟動完畢之後就會調用一次,建立過程如下:
提示:應用程式啟動之後,先建立application,再建立它的代理,之後建立uiwindow。uiwindow繼承自uiview。
2.把view添加到uiwindow
建立一個控制器,把view添加到uiwindow上面(有兩種方式)
(1)直接将控制器的view添加到uiwindow中,并不理會它對應的控制器
[self.window addsubview:vc.view];
(2)設定uiwindow的根控制器,自動将rootviewcontroller的view添加到window中,負責管理rootviewcontroller的生命周期
[self.window.rootviewcontroller=vc];
兩個方法的差別:
以後的開發中,建議使用(2).因為方法(1)存在一些問題,比如說控制器上面可能由按鈕,需要監聽按鈕的點選事件,如果是1,那麼按鈕的事件應該由控制器來進行管理。但控制器是一個局部變量,控制器此時已經不存在了,但是控制器的view還在,此時有可能會報錯。注意:方法執行完,這個控制器就已經不存在了。
問題描述1:當view發生一些事件的時候,通知控制器,但是控制器已經銷毀了,是以可能出現未知的錯誤。
問題描述2:添加一個開關按鈕,讓螢幕360度旋轉(兩者的效果不一樣)。當發生螢幕旋轉事件的時候,uiapplication對象會将旋轉事件傳遞給uiwindow,uiwindow又會将旋轉事件傳遞給它的根控制器,由根控制器決定是否需要旋轉
uiapplication->uiwindow->根控制器(第一種方式沒有根控制器,是以不能跟着旋轉)。
提示:不通過控制器的view也可以做開發,但是在實際開發中,不要這麼做,不要直接把view添加到uiwindow上面去。因為,難以管理。
3.在有storyboard的項目中,uiwindow是如何建立的?
為什麼建立一個storyboard,沒有看到建立uiwindow的過程?
它其實是把建立uiwindow的過程給屏蔽起來了。可以把代理的uiwindow的屬性的值列印出來nslog(@“window=%p”,self.window);列印出來确實是有值的,說明确實建立了uiwindow.不僅建立了uiwindow,預設還建立了uiwindow對應的控制器,也可以列印進行檢視。nslog(@“%@“,self.window.rootviewcontroller);
有storyboard的項目中的建立過程:
當使用者點選應用程式圖示的時候,先執行main函數,執行uiapplicationmain(),根據其第三個和第四個參數建立application,建立代理,并且把代理設定給application(看項目配置檔案info.plist裡面的storyboard的name,根據這個name找到對應的storyboard),開啟一個事件循環,當程式加載完畢,他會調用代理的didfinishlaunchingwithoptions:方法。在調用didfinishlaunchingwithoptions:方法之前,會加載storyboard,在加載的時候建立一個window,接下來會建立箭頭所指向的控制器,把該控制器設定為uiwindow的根控制器,接下來再将window顯示出來,即看到了運作後顯示的界面。(提示:關于這部分可以檢視story的初始化的文檔)
三、如何擷取window?
1.主視窗和次視窗
【self.window makekeyandvisible】讓視窗成為主視窗,并且顯示出來。有這個方法,才能把資訊顯示到螢幕上。
因為window有makekeyandvisible這個方法,可以讓這個window憑空的顯示出來,而其他的view沒有這個方法,是以它隻能依賴于window,window顯示出來後,view才依附在window上顯示出來。
【self.window make keywindow】//讓uiwindow成為主視窗,但不顯示。
2.擷取uiwindow
(1)[uiapplication sharedapplication].windows 在本應用中打開的uiwindow清單,這樣就可以接觸應用中的任何一個uiview對象(平時輸入文字彈出的鍵盤,就處在一個新的uiwindow中)
(2)[uiapplication sharedapplication].keywindow(擷取應用程式的主視窗)用來接收鍵盤以及非觸摸類的消息事件的uiwindow,而且程式中每個時刻隻能有一個uiwindow是keywindow。
提示:如果某個uiwindow内部的文本框不能輸入文字,可能是因為這個uiwindow不是keywindow
(3)view.window獲得某個uiview所在的uiwindow
四、四大對象的關系圖
五、主視窗和次視窗說明
代碼:
代碼說明:
再建立一個視窗(主視窗和次視窗的差別)
局部變量,需要定義一個window屬性來儲存變量。
window的屬性定義為strong,就是為了讓其不銷毀。
一個應用程式隻能有一個主視窗,程式中建立了兩個window,那麼誰是主視窗?後面的視窗能覆寫前面的視窗。
提示:如果uitextfield不顯示,可以考慮設定它的樣式,因為其建立預設是虛線的,沒有邊框。
在ios7裡邊,主視窗和次視窗是沒有差別的
在ios7以前中有差別:哪個是主視窗,後面設定為主視窗會把之前設定的覆寫掉。(隻有主視窗才能響應鍵盤的輸入事件,如果不能輸入内容,可以檢視是否是顯示在主視窗上,不在主視窗上的不能響應。)
六、補充說明
在有storyboard中的建立過程:
先執行main函數,執行uiapplicationmain(),根據其第三個和第四個參數建立application,建立代理,并且把代理設定給application,根據項目配置檔案info.plist裡面的storyboard的name,找到對應的storyboard,接下來建立一個window,之後建立它的初始化控制器(就是箭頭所指向的控制器),自動把該控制器設定為uiwindow的根控制器,接下來再将window顯示出來,即看到了運作後顯示的界面。
注意這個控制器屬性面闆上的“初始化控制器屬性”。
在沒有storyboard中的建立過程:
先執行main函數,執行uiapplicationmain(),根據其第三個和第四個參數建立application,建立代理,并且把代理設定給application,開啟一個事件循環,當程式加載完畢,他會調用代理的didfinishlaunchingwithoptions:方法。在該方法中,會建立一個window,然後建立一個控制器,并把該控制器設定為uiwindow的根控制器,接下來再将window顯示出來,即看到了運作後顯示的界面。