UIView的生命周期總結

UIView的生命周期總結


來源: bestswifter(@bestswifter)

鏈接:https://bestswifter.com/uiviewlifetime/


序言:


loadView巫员、viewDidLoad、viewDidAppear、initWithNibName拄显、awakeFromNib等經常出現(xiàn)在UIViewController中的方法介紹。

這些方法分別用來作哪些工作讯屈,換言之,創(chuàng)建自定義的View時代碼放到以上哪個方法中胁出。

一個UIView的生命周期是怎樣的。以上幾個方法的調用順序如何忆家。

通過IB和代碼加載視圖犹菇,有什么區(qū)別


UIViewController


視圖層次和根視圖


每個視圖控制器都維護一個視圖層次(view hierarchy)。


因為每個視圖都有自己的子視圖芽卿,這個視圖層次其實也可以理解為一棵樹狀的數(shù)據(jù)結構揭芍。而樹的根節(jié)點,也就是根視圖(root view)卸例,在UIViewController中以view屬性称杨。它可以被看做是其他所有子視圖的容器。


視圖的加載方式


UIViewController采用懶加載的方式筷转,也就是說第一次訪問到view屬性時才會加載或創(chuàng)建它姑原。由于視圖由視圖控制器管理,所以討論視圖的加載方式時呜舒,主要討論視圖控制器的加載方式锭汛。


通過Storyboard加載:這是蘋果推薦的方式,也是未來的趨勢袭蝗。

通過這種方式創(chuàng)建UIViewController對象的話唤殴,首先生成UIStoryboard類型的對象,然后調用這個對象的instantiateViewControllerWithIdentifier:方法


通過Nib文件加載:

Nib文件其實就是xib文件呻袭,Storyboard相當于是聚合了多個nib文件眨八,并且添加了對不同的UIViewController之間的segue和relationship的管理。但總的實現(xiàn)原理非常類似


通過這種方式加載視圖,需要調用UIViewController類的initWithNibName:bundle:方法


通過loadview方法加載:


這就是通過代碼加載左电。這需要我們在loadView 方法中廉侧,通過編程創(chuàng)建自己的視圖層次,并且把把根視圖賦值給UIViewController的view屬性篓足。


因此段誊,通過代碼自定義View的時候,loadView 方法大概是這樣的:


- (void)loadView{

? ?self.view = [[XXXView alloc] init];

}


處理視圖相關通知


當視圖的可見性發(fā)生變化時栈拖,視圖控制器會自動調用一系列方法來響應變化连舍。


所有可能的狀態(tài)、方法和狀態(tài)之間的轉換關系在下圖中被明確標出涩哟。


可以看到每一個will方法都有自己對應的did方法索赏。但是如果我們在will方法中開始一個任務,不僅要在對應的did方法中結束它贴彼,還要考慮到和這個will方法相反的那個will方法(注意到Appearing和Disappearing這兩個狀態(tài)是可以互相轉化的)


在運行時展示View


UIKit極大的簡化了加載和展示View的過程潜腻,它大概會按照以下順序執(zhí)行一些任務:


通過storyboard文件中的信息實例化視圖

連接outlet和action

把根視圖賦值給UIViewController的view屬性(其實就是調用loadView 方法)

調用UIViewController的awakeFromNib方法。要注意器仗,在調用方法前融涣,的trait collecion為空且子視圖的位置可能不正確

調用UIViewController的viewDidLoad方法童番。


此時已經完成了視圖的加載工作,在展示到屏幕之前威鹿,還有以下幾個步驟:


調用UIViewController的viewWillAppear方法剃斧。

更新視圖的布局

把視圖展示到屏幕上

調用UIViewController的viewDidAppear方法。


awakeFromNib方法


至此忽你,第一個問題已經幾乎解釋完了幼东,還剩一個awakeFromNib方法。


我們已經知道檀夹,awakeFromNib方法被調用時筋粗,所有視圖的outlet和action已經連接,但還沒有被確定炸渡。這個方法可以算作是和視圖控制器的實例化配合在一起使用的娜亿,因為有些需要根據(jù)用戶喜好來進行設置的內容,無法存在storyboard中蚌堵,所以可以在awakeFromNib方法中被加載進來买决。


awakeFromNib方法在視圖控制器的生命周期內只會被調用一次。因為它和視圖控制器從nib文件中的解檔密切相關吼畏,和view的關系卻不大督赤。


具體方法的解釋


loadView方法


當執(zhí)行到loadView方法時,視圖控制器已經從nib文件中被解檔并創(chuàng)建好了泻蚊,接下來的任務主要是對view進行初始化躲舌。


loadView方法在UIViewController對象的view屬性被訪問到且為空的時候調用。

這是它與awakeFromNib方法的一個區(qū)別性雄。假設我們在處理內存警告時釋放view屬性(其實并不應該這么做没卸,這里舉個例子):self.view = nil。因此loadView方法在視圖控制器的生命周期內可能會被多次調用秒旋。


這個方法不應該被直接調用约计,而是由系統(tǒng)自動調用。它會加載或創(chuàng)建一個view并把它賦值給UIViewController的view屬性迁筛。


在創(chuàng)建view的過程中煤蚌,首先會根據(jù)nibName去找對應的Nib文件然后加載。如果nibName為空细卧,或找不到對應的Nib文件尉桩,則會創(chuàng)建一個空視圖(這種情況一般是純代碼,也就是為什么說代碼構建View的時候贪庙,要重寫loadView 方法)魄健。


注意在重寫loadView方法的時候,不要調用父類的方法插勤。


viewDidLoad方法


loadView方法執(zhí)行完之后,就會執(zhí)行viewDidLoad方法。此時整個視圖層次(view hierarchy)已經被放到內存中农尖。


無論是從nib文件加載析恋,還是通過純代碼編寫界面,viewDidLoad方法都會執(zhí)行盛卡。我們可以重寫這個方法助隧,對通過nib文件加載的view做一些其他的初始化工作。比如可以移除一些視圖滑沧,修改約束并村,加載數(shù)據(jù)等。


viewWillAppear和viewDidAppear方法


在視圖加載完成滓技,并即將顯示在屏幕上時哩牍,會調用viewWillAppear方法,在這個方法里令漂,可以改變當前屏幕方向或狀態(tài)欄的風格等膝昆。


當viewWillAppear方法執(zhí)行完后,系統(tǒng)會執(zhí)行viewDidAppear方法叠必。在這個方法中荚孵,還可以對視圖做一些關于展示效果方面的修改。


視圖的生命歷程


到目前為止纬朝,我們已經了解了每個方法的作用收叶,接下來就把整個流程梳理一遍。


-[ViewController initWithCoder:]或-[ViewController initWithNibName:Bundle]:首先從歸檔文件中加載UIViewController對象共苛。即使是純代碼判没,也會把nil作為參數(shù)傳給后者。

-[UIView awakeFromNib]:作為第一個方法的助手俄讹,方便處理一些額外的設置哆致。

-[ViewController loadView]:創(chuàng)建或加載一個view并把它賦值給UIViewController的view屬性

-[ViewController viewDidLoad]:此時整個視圖層次(view hierarchy)已經被放到內存中,可以移除一些視圖患膛,修改約束摊阀,加載數(shù)據(jù)等

-[ViewController viewWillAppear:]:視圖加載完成,并即將顯示在屏幕上,還沒有設置動畫踪蹬,可以改變當前屏幕方向或狀態(tài)欄的風格等胞此。

-[ViewController viewWillLayoutSubviews]:即將開始子視圖位置布局

-[ViewController viewDidLayoutSubviews]:用于通知視圖的位置布局已經完成

-[ViewController viewDidAppear:]:視圖已經展示在屏幕上,可以對視圖做一些關于展示效果方面的修改跃捣。

-[ViewController viewWillDisappear:]:視圖即將消失

-[ViewController viewDidDisappear:]:視圖已經消失


如果考慮UIViewController可能在某個時刻釋放整個view漱牵。那么再次加載視圖時顯然會從步驟3開始。因為此時的UIViewController對象依然存在疚漆。


總結


只有init系列的方法,如initWithNibName需要自己調用酣胀,其他方法如loadView和awakeFromNib則是系統(tǒng)自動調用刁赦。而viewWill/Did系列的方法則類似于回調和通知,也會被自動調用闻镶。

純代碼寫視圖布局時需要注意甚脉,要手動調用loadView方法,而且不要調用父類的loadView方法铆农。純代碼和用IB的區(qū)別僅存在于loadView方法及其之前牺氨,編程時需要注意的也就是loadView方法。

除了initWithNibName和awakeFromNib方法是處理視圖控制器外墩剖,其他方法都是處理視圖猴凹。這兩個方法在視圖控制器的生命周期里只會調用一次。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末岭皂,一起剝皮案震驚了整個濱河市郊霎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蒲障,老刑警劉巖歹篓,帶你破解...
    沈念sama閱讀 206,311評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異揉阎,居然都是意外死亡庄撮,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,339評論 2 382
  • 文/潘曉璐 我一進店門毙籽,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洞斯,“玉大人,你說我怎么就攤上這事坑赡±尤纾” “怎么了?”我有些...
    開封第一講書人閱讀 152,671評論 0 342
  • 文/不壞的土叔 我叫張陵毅否,是天一觀的道長亚铁。 經常有香客問我,道長螟加,這世上最難降的妖魔是什么徘溢? 我笑而不...
    開封第一講書人閱讀 55,252評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮捆探,結果婚禮上然爆,老公的妹妹穿的比我還像新娘。我一直安慰自己黍图,他們只是感情好曾雕,可當我...
    茶點故事閱讀 64,253評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著助被,像睡著了一般剖张。 火紅的嫁衣襯著肌膚如雪切诀。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,031評論 1 285
  • 那天搔弄,我揣著相機與錄音趾牧,去河邊找鬼。 笑死肯污,一個胖子當著我的面吹牛,可吹牛的內容都是我干的吨枉。 我是一名探鬼主播蹦渣,決...
    沈念sama閱讀 38,340評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼貌亭!你這毒婦竟也來了柬唯?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,973評論 0 259
  • 序言:老撾萬榮一對情侶失蹤圃庭,失蹤者是張志新(化名)和其女友劉穎锄奢,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剧腻,經...
    沈念sama閱讀 43,466評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡拘央,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,937評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了书在。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灰伟。...
    茶點故事閱讀 38,039評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖泞遗,靈堂內的尸體忽然破棺而出钢坦,到底是詐尸還是另有隱情武学,我是刑警寧澤,帶...
    沈念sama閱讀 33,701評論 4 323
  • 正文 年R本政府宣布挡爵,位于F島的核電站,受9級特大地震影響甚垦,放射性物質發(fā)生泄漏茶鹃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,254評論 3 307
  • 文/蒙蒙 一制轰、第九天 我趴在偏房一處隱蔽的房頂上張望前计。 院中可真熱鬧,春花似錦垃杖、人聲如沸男杈。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,259評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽伶棒。三九已至旺垒,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肤无,已是汗流浹背先蒋。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留宛渐,地道東北人竞漾。 一個月前我還...
    沈念sama閱讀 45,497評論 2 354
  • 正文 我出身青樓,卻偏偏與公主長得像窥翩,于是被迫代替她去往敵國和親业岁。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,786評論 2 345

推薦閱讀更多精彩內容