UIView的生命周期

思考

  1. loadView汽纠、viewDidLoad卫键、viewDidAppear、initWithNibName虱朵、awakeFromNib等經(jīng)常出現(xiàn)在UIViewController中的方法介紹莉炉,這些方法分別用來做哪些工作钓账?換言之,創(chuàng)建自定義的view的代碼放到以上哪個方法中絮宁?
  2. 一個UIView的生命周期是怎樣的梆暮?以上幾個方法的調(diào)用順序如何?
  3. 通過IB和代碼加載視圖绍昂,有什么區(qū)別啦粹?

UIViewController

  • 視圖層次和根視圖:每個視圖控制器都維護(hù)一個視圖層次(view hierarchy)。因為每個視圖都有自己的子視圖窘游,這個視圖層次其實(shí)也可以理解為一棵樹狀的數(shù)據(jù)結(jié)構(gòu)唠椭。而樹的根節(jié)點(diǎn),也就是根視圖(root view)忍饰,在UIViewController中以view屬性贪嫂,它可以被看做是其他所有子視圖的容器。
  • 視圖加載方式:UIViewController采用懶加載的方式艾蓝,也就是說第一次訪問到view屬性時才會加載或創(chuàng)建它力崇。由于視圖由視圖控制器管理,所以討論視圖的加載方式時赢织,主要討論視圖控制器的加載方式亮靴。
  • 通過Storyboard加載:這是蘋果推薦的方式,通過這種方式創(chuàng)建UIViewController對象的話敌厘,首先生成UIStoryboard類型的對象台猴,然后調(diào)用這個對象的 intantiateViewControllerWithIdentifier: 方法。
  • 通過Nib文件加載:Nib文件其實(shí)就是xib文件俱两,Storyboard相當(dāng)于是聚合了多個nib文件饱狂,并且添加了對不同的UIViewController之間的segue和relationship的管理,但總的實(shí)現(xiàn)原理非常類似宪彩。通過這種方式加載視圖休讳,需要調(diào)用UIViewController類的 initWithNibName: bundle: 方法。
  • 通過loadView方法加載:這就是通過代碼加載尿孔。這需要我們在loadView方法中俊柔,通過編程創(chuàng)建自己的視圖層次,并且把根視圖賦值給UIViewController的view屬性活合。因此通過代碼自定義view的時候雏婶,loadView方法大概是這樣的:
-(void)loadView
{
     self.view=[[XXXView alloc] init];
}

處理視圖相關(guān)通知

  • 當(dāng)視圖的可見性發(fā)生變化時,視圖控制器會自動調(diào)用一系列方法來響應(yīng)變化白指,所有可能的狀態(tài)留晚、方法和狀態(tài)之間的轉(zhuǎn)換關(guān)系在下圖中被明確標(biāo)出


    處理視圖相關(guān)通知

    可以看到每一個will方法都有自己對應(yīng)的did方法。但是如果我們在will方法中開始一個任務(wù)告嘲,不僅要在對應(yīng)的did方法中結(jié)束它错维,還要考慮到和這個will方法相反的那個will方法(注意到Appearing和Disappearing者兩個狀態(tài)是可以互相轉(zhuǎn)化的)

在運(yùn)行時展示View

  • UIKit極大的簡化了加載和展示View的過程奖地,它大概會按照以下順序執(zhí)行一些任務(wù):
    • 通過storyboard文件中的信息實(shí)例化視圖
    • 連接outlet和action
    • 調(diào)用UIViewController的awakeFromNib方法,要注意赋焕,在調(diào)用方法前的 traitcollection 為空且子視圖的位置可能不正確
    • 把根視圖賦值給UIViewController的view屬性(其實(shí)就是調(diào)用loadView方法)
    • 調(diào)用UIViewController的viewDidLoad方法
  • 此時已經(jīng)完成了視圖的加載工作参歹,在展示到屏幕之前,還有以下幾個步驟:
    • 調(diào)用UIViewController的viewWillAppear方法
    • 更新視圖的布局
    • 把視圖展示到屏幕上
    • 調(diào)用UIViewController的viewDidAppear方法
  • 至此隆判,第一個問題已經(jīng)幾乎解釋完了犬庇,還剩下一個awakeFromNib方法
    • 我們已經(jīng)知道,awakeFromNib方法被調(diào)用時侨嘀,所有視圖的outlet和action已經(jīng)連接械筛,但還沒有確定。這個方法可以算作是和視圖控制器的實(shí)例化配合在一起使用的飒炎,因為有些需要根據(jù)用戶的喜好來進(jìn)行設(shè)置的內(nèi)容,無法存在storyboard中笆豁,所以可以在awakeFromNib方法中被加載進(jìn)來郎汪。
    • awakeFromNib方法在視圖控制器的生命周期內(nèi)只會被調(diào)用一次。因為它和視圖控制器從nib文件中的解檔密切相關(guān)育特,和view的關(guān)系卻不大尖殃。

具體方法的解釋

  • loadView 方法
    • 當(dāng)執(zhí)行到loadView方法時偷溺,視圖控制器已經(jīng)從nib文件中被解檔并創(chuàng)建好了,接下來的任務(wù)主要是對view進(jìn)行初始化
    • loadView方法在UIViewController對象的view屬性被訪問到且為空的時候調(diào)用照筑。
    • 這是它與awakeFromNib方法的一個區(qū)別。假如我們在處理內(nèi)存警告時釋放view屬性(其實(shí)并不應(yīng)該這么做瘦陈,這里舉個例子):self.view = nil凝危。因此loadView方法在視圖控制器的生命周期內(nèi)可能會被多次調(diào)用。
    • 這個方法不應(yīng)該被直接調(diào)用晨逝,而是有系統(tǒng)自動調(diào)用蛾默。它會加載或創(chuàng)建一個view并把它賦值給UIViewController的view屬性。
    • 在創(chuàng)建view的過程中捉貌,首先會根據(jù)nibName去找對應(yīng)的Nib文件然后加載支鸡,如果nibName為空,或找不到對應(yīng)的Nib文件趁窃,則創(chuàng)建一個空視圖(這種情況一般是純代碼牧挣,也就是為什么說代碼構(gòu)建view的時候,要重寫loadView方法)醒陆。
    • 注意在重寫loadView方法的時候瀑构,不要調(diào)用父類的方法。
  • viewDidLoad 方法
    • loadView方法執(zhí)行完之后统求,就會執(zhí)行viewDidLoad方法检碗。此時整個視圖層次(view hierarchy)已經(jīng)被放在內(nèi)存中据块。
    • 無論是從nib文件加載,還是通過純代碼編寫界面折剃,viewDidLoad方法都會執(zhí)行另假,我們可以重寫這個方法,對通過nib文件加載的view做一些其他的初始化工作怕犁。比如可以移除一些視圖边篮,修改約束,加載數(shù)據(jù)等
  • viewWillAppear和viewDidAppear方法
    • 在視圖加載完成奏甫,并即將顯示在屏幕上時戈轿,會調(diào)用viewWillAppear方法,在這個方法里阵子,可以改變當(dāng)前屏幕的方向或狀態(tài)欄的風(fēng)格等思杯。
    • 當(dāng)viewWillAppear方法執(zhí)行完后,系統(tǒng)會執(zhí)行viewDidAppear方法挠进。在這個方法中色乾,還可以對視圖做一些關(guān)于展示效果方面的修改。

視圖的生命周期
到目前為止领突,我們已經(jīng)了解了每個方法的作用暖璧,接下來就把整個流程梳理一遍。

  1. -[ViewController initWithCoder:] 或 -[ViewController initWithNibName: Bundle: ] 首先從歸檔文件中加載UIViewController對象君旦。即使是純代碼澎办,也會把nil作為參數(shù)傳給后者。
  2. -[UIView awakeFromNib:] 作為第一個方法的助手金砍,方便處理一些額外的設(shè)置局蚀。
  3. -[ViewController loadView] 創(chuàng)建或加載一個view并把它賦值給UIViewController的view屬性
  4. -[ViewController viewDidLoad] 此時整個視圖層次(view hierarchy)已經(jīng)被放到內(nèi)存中,可以移除一些視圖恕稠,修改約束至会,加載數(shù)據(jù)等
  5. -[ViewController viewWillAppear:] 視圖加載完成,并即將顯示在屏幕上谱俭,還沒有設(shè)置動畫奉件,可以改變當(dāng)前屏幕方向和狀態(tài)欄的風(fēng)格等
  6. -[ViewController viewWillLayoutSubviews] 即將開始子視圖位置布局
  7. -[ViewController viewDidLayoutSubviews] 用于通知視圖的位置布局已經(jīng)完成
  8. -[ViewController viewDidAppear:] 視圖已經(jīng)展示在屏幕上,可以對視圖做一些關(guān)于展示效果方面的修改
  9. -[ViewController viewWillDisAppear:] 視圖即將消失
  10. -[ViewController viewDidDisAppear:] 視圖已經(jīng)消失

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

總結(jié)

  • 只有init系列的方法凑懂,如initWithNibName需要自己調(diào)用煤痕,其他方法如loadView和awakeFromNib則是系統(tǒng)自動調(diào)用。而viewWill/Did系列的方法則類似于回調(diào)和通知,也會自動調(diào)用摆碉。
  • 純代碼寫視圖布局時需要注意塘匣,要手動調(diào)用loadView方法,而且不要調(diào)用父類的loadView方法巷帝。純代碼和用IB的區(qū)別僅存在于loadView方法及其之前忌卤,編程時需要注意的也就是loadView方法。
  • 除了initWithNibName和awakeFromNib方法是處理視圖控制器外楞泼,其他方法都是處理視圖驰徊。這兩個方法在視圖控制器的生命周期里只會調(diào)用一次。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堕阔,一起剝皮案震驚了整個濱河市棍厂,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌超陆,老刑警劉巖牺弹,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異时呀,居然都是意外死亡例驹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門退唠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人荤胁,你說我怎么就攤上這事瞧预。” “怎么了仅政?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵垢油,是天一觀的道長。 經(jīng)常有香客問我圆丹,道長滩愁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任辫封,我火速辦了婚禮硝枉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘倦微。我一直安慰自己妻味,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布欣福。 她就那樣靜靜地躺著责球,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雏逾,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天嘉裤,我揣著相機(jī)與錄音,去河邊找鬼栖博。 笑死屑宠,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的笛匙。 我是一名探鬼主播侨把,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼妹孙!你這毒婦竟也來了秋柄?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤蠢正,失蹤者是張志新(化名)和其女友劉穎骇笔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嚣崭,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡笨触,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了雹舀。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芦劣。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖说榆,靈堂內(nèi)的尸體忽然破棺而出虚吟,到底是詐尸還是另有隱情,我是刑警寧澤签财,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布串慰,位于F島的核電站,受9級特大地震影響唱蒸,放射性物質(zhì)發(fā)生泄漏邦鲫。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一神汹、第九天 我趴在偏房一處隱蔽的房頂上張望庆捺。 院中可真熱鬧,春花似錦屁魏、人聲如沸疼燥。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽醉者。三九已至但狭,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撬即,已是汗流浹背立磁。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留剥槐,地道東北人唱歧。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像粒竖,于是被迫代替她去往敵國和親颅崩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容