iOS開發(fā) - 深入理解控制器與類以及view的加載


引言:
ViewController是iOS開發(fā)中MVC模式中的C(視圖控制器),ViewController是view的controller,ViewController的職責(zé)主要包括管理內(nèi)部各個view的加載顯示和卸載,同時負(fù)責(zé)與其他ViewController的通信和協(xié)調(diào)。


I. 簡介


在IOS中,有兩類ViewController:

用于展示內(nèi)容:
比如UIViewControllerUITableViewController等,同時還可以自定義繼承自UIViewController的UIViewController;

ViewController容器:
比如,UINavigationViewControllerUITabBarController等,UINavigationController是以Stack的形式來存儲和管理ViewController,UITabBarController是以Array的形式來管理ViewController。

不管是哪類ViewController,都繼承自UIViewController


II. UIViewController


控制器從創(chuàng)建到銷毀方法的執(zhí)行順序

load->
initialize->
init(initWithNibName)—>  
loadView—>
viewDidLoad—>
viewWillApper—>
viewDidApper—>  
viewWillDisapper—>
viewDidDisapper—>
viewWillUnload->  
viewDidUnload—>
dealloc

其中viewWillUnloadviewDidUnLoad在iOS6以后就過期了. 收到low-memory時系統(tǒng)不會釋放view,而只是釋放controllerresource`。

注意點:

LoadView:

  1. 控制器調(diào)用loadView方法創(chuàng)建控制器的view.當(dāng)控制器的view存在了就不會調(diào)用.
  2. 不要再LoadView中調(diào)用[super loadView],會影響CPU性能

蘋果官方文檔:

You should never call this method directly. The view controller calls this method when its view property is requested but is currently nil. This method loads or creates a view and assigns it to the view property.

當(dāng)系統(tǒng)要展示這個控制器view的時候,會先去view的getter方法中尋找有沒有返回view,如果view == nil,系統(tǒng)就會主動去調(diào)用這個方法.

控制器的view都是懶加載,當(dāng)需要展示的時候才會去創(chuàng)建

  1. 懶加載:重寫getter方法
  2. 好處:不用管什么時候需要創(chuàng)建,做到要用時再創(chuàng)建


III. view的加載過程


這里指的View是指Controller的View。它作為Controler的屬性,生命周期在Controller的生命周期內(nèi)。就是說你的Controller不能在view釋放前就釋放了。

從代碼中加載view

代碼創(chuàng)建

從storyboard/xib中創(chuàng)建view

實現(xiàn)過程

view的實現(xiàn)過程

方法調(diào)用順序

+ (id)alloc
分配內(nèi)存;

- (id)init 方法(包括其他-(id)init...方法)
只允許調(diào)用一次,并且要與 alloc方法 寫在一起,在init方法中申請的內(nèi)存,要在dealloc方法中釋放(或者其他地方);

- (void)awakeFromNib
使用Xib初始化后會調(diào)用此方法,一般不會重寫此方法;

- (void)loadView
如果使用Xib創(chuàng)建ViewController,就不要重寫該方法。一般不會修改此方法;

- (void)viewDidLoad
視圖加載完成之后被調(diào)用,這個方法很重要,可以在此增加一些自己定義的控件,注意此時view的frame不一定是顯示時候的frame,真實的frame會在 - (void)viewDidAppear: 后。
在iOS6.0+版本中在對象的整個生命周期中只會被調(diào)用一次,這里要注意在iOS3.0~iOS5.X版本中可能會被重復(fù)調(diào)用,當(dāng)ViewController收到內(nèi)存警告后,會釋放View,并調(diào)用viewDidUnload,之后會重新調(diào)用viewDidLoad,所以要支持iOS6.0以前版本的童鞋要注意這里的內(nèi)存管理。

- (void)viewWillAppear:(BOOL)animated
view 將要顯示的時候,可以在此加載一些圖片,和一些其他占內(nèi)存的資源;

- (void)viewDidAppear:(BOOL)animated
view 已經(jīng)顯示的時候調(diào)用;

- (void)viewWillDisappear:(BOOL)animated
view 將要隱藏的時候,可以在此將一些占用內(nèi)存比較大的資源先釋放掉,在 viewWillAppear: 中重新加載。如:圖片/聲音/視頻。如果View已經(jīng)隱藏而又在內(nèi)存中保留這些在顯示前不會被調(diào)用的資源,那么App閃退的幾率會增加,尤其是ViewController比較多的時候;

- (void)viewDidAppear:(BOOL)animated
view 已經(jīng)隱藏的時候調(diào)用;

- (void)dealloc
不要手動調(diào)用此方法,當(dāng)引用計數(shù)值為0的時候,系統(tǒng)會自動調(diào)用此方法。


IV. 類相關(guān)方法


+(void)load
當(dāng)一個類被加載時調(diào)用,只加載一次

+(void)initialize
當(dāng)本類或者子類被加載時調(diào)用,可能調(diào)用多次

-(instancetype)init
用代碼創(chuàng)建類的時候調(diào)用,只能做一些初始化操作,不能設(shè)置控件的frame,init其實是去調(diào)用initWithFrame,只不過frame為CGRectZero

-(instancetype)initWithFrame:(CGRect)frame
用代碼創(chuàng)建類的時候調(diào)用,只能做一些初始化操作,不能在這設(shè)置控件的frame,如果已經(jīng)知道了frame,那么在這里設(shè)置子控件的frame是沒有問題的,但是如果外界使用init的方式創(chuàng)建,最終也會調(diào)用initWithFrame方法,此時的frame傳進(jìn)來是0,那么,在這個方法里面設(shè)置的子控件的frame也會為0.所以,為了嚴(yán)謹(jǐn)起見,最好不要在這個方法里面設(shè)置子控件的frame。

-(instancetype)initWithCoder:(NSCoder *)aDecoder
從xib/storyboard中加載就會調(diào)用此方法,只能在這個方法做一些一次性設(shè)置,不能設(shè)置控件的frame

-(void)awakeFromNib
從文件中加載.就會調(diào)用此方法,可以在這個方法中設(shè)置frame

-(void)layoutSubviews
如果你想改變子視圖的默認(rèn)布局時才需要去重寫 layoutSubviews 方法。

使用 NavigationController 去 Push 切換顯示的View, 調(diào)用的順序

例如 從 A 控制器 Push 顯示 B 控制器,
[self.navigationController pushViewController:B animated:YES]

1. 加載B控制器的View(如果沒有的話);
2. 調(diào)用 A 的 - (void)viewWillDisappear:(BOOL)animated; A將要隱藏
3. 調(diào)用 B 的 - (void)viewWillAppear:(BOOL)animated; B將要顯示
4. 調(diào)用 A 的 - (void)viewDidDisappear:(BOOL)animated;A已經(jīng)隱藏
5. 調(diào)用 B 的 - (void)viewDidAppear:(BOOL)animated; B已經(jīng)顯示


V. 收到內(nèi)存警告系統(tǒng)執(zhí)行步驟


- (void)didReceiveMemoryWarning
iOS6.0以后 內(nèi)存不夠用時,會調(diào)用這個方法,接收到內(nèi)存警告.




最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 27、ViewController的didReceiveMemoryWarning是在什么時候調(diào)用的?默認(rèn)的操作是...
    煙雨平生花飛舞閱讀 695評論 0 1
  • ViewController是iOS開發(fā)中MVC模式中的C(視圖控制器),ViewController是view的...
    iiNico閱讀 2,184評論 4 10
  • 1、截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的數(shù)據(jù),分別輸出它們 ...
    強子ly閱讀 3,144評論 8 46
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,666評論 30 472
  • Focus on creating the simplest, simplest, simplest, simpl...
    北極熊UM閱讀 1,257評論 0 0

友情鏈接更多精彩內(nèi)容