UIView生命週期相關函數
//構造方法,初始化時調用,不會調用init方法
- (instancetype)initWithFrame:(CGRect)frame;
//構造方法,內部會調用initWithFrame方法
- (instancetype)init;
//xib歸檔初始化視圖後調用,如果xib中添加了子控件會在didAddSubview方法調用後調用
- (instancetype)initWithCoder:(NSCoder *)aDecoder;
//喚醒xib,可以佈局子控件
- (void)awakeFromNib;
//父視圖將要更改爲指定的父視圖,當前視圖被添加到父視圖時調用
- (void)willMoveToSuperview:(UIView *)newSuperview;
//父視圖已更改
- (void)didMoveToSuperview;
//其窗口對象將要更改
- (void)willMoveToWindow:(UIWindow *)newWindow;
//窗口對象已經更改
- (void)didMoveToWindow;
//佈局子控件
- (void)layoutSubviews;
//繪製視圖
- (void)drawRect:(CGRect)rect;
//從父控件中移除
- (void)removeFromSuperview;
//銷燬
- (void)dealloc;
//添加子控件時調用
- (void)didAddSubview:(UIView *)subview;
//將要移除子控件
- (void)willRemoveSubview:(UIView *)subview;
init方式創建視圖,並添加到父視圖中展示,不添加子控件,其生命週期調用順序爲:
[NoXibView initWithFrame:]
[NoXibView init]
[NoXibView willMoveToSuperview:]
[NoXibView didMoveToSuperview]
[NoXibView willMoveToWindow:]
[NoXibView didMoveToWindow]
[NoXibView layoutSubviews]
initWithFrame方式創建視圖,並添加到父視圖中展示,不添加子控件,其生命週期調用順序爲:
[NoXibView initWithFrame:]
[NoXibView willMoveToSuperview:]
[NoXibView didMoveToSuperview]
[NoXibView willMoveToWindow:]
[NoXibView didMoveToWindow]
[NoXibView layoutSubviews]
[NoXibView drawRect:]
移除銷燬是調用順序:
[NoXibView willMoveToWindow:]
[NoXibView didMoveToWindow]
[NoXibView willMoveToSuperview:]
[NoXibView didMoveToSuperview]
[NoXibView removeFromSuperview]
[NoXibView dealloc]
添加子控件展示時調用順序:
[NoXibView initWithFrame:]
[NoXibView didAddSubview:]
[NoXibView willMoveToSuperview:]
[NoXibView didMoveToSuperview]
[NoXibView willMoveToWindow:]
[NoXibView didMoveToWindow]
[NoXibView layoutSubviews]
[NoXibView drawRect:]
添加子控件移除銷燬時調用順序:
[NoXibView willMoveToWindow:]
[NoXibView didMoveToWindow]
[NoXibView willMoveToSuperview:]
[NoXibView didMoveToSuperview]
[NoXibView removeFromSuperview]
[NoXibView dealloc]
[NoXibView willRemoveSubview:]
xib創建初始化視圖, xib中不添加子控件時調用順序:
[XibView initWithCoder:]
[XibView awakeFromNib]
[XibView willMoveToSuperview:]
[XibView didMoveToSuperview]
[XibView willMoveToWindow:]
[XibView didMoveToWindow]
[XibView layoutSubviews]
[XibView layoutSubviews]
[XibView drawRect:]
xib創建初始化視圖, xib中添加子控件時調用順序:
[XibView didAddSubview:]
[XibView initWithCoder:]
[XibView awakeFromNib]
[XibView willMoveToSuperview:]
[XibView didMoveToSuperview]
[XibView willMoveToWindow:]
[XibView didMoveToWindow]
[XibView layoutSubviews]
[XibView layoutSubviews]
[XibView drawRect:]
移除銷燬時調用順序,有子控件:
[XibView willMoveToWindow:]
[XibView didMoveToWindow]
[XibView willMoveToSuperview:]
[XibView didMoveToSuperview]
[XibView removeFromSuperview]
[NoXibView dealloc]
[NoXibView willRemoveSubview:]
UIView生命週期總結:
- init方法初始化視圖,內部會調用initWithFrame方法,不會調用initWithCoder和awakeFromNib方法;
- xib歸檔創建視圖會觸發initWithCoder和awakeFromNib方法,不再調用init和initWithFrame方法;
- 添加視圖調用addSubview方法會觸發didAddSubview犯法.
- willMoveToSuperview和didMoveToSuperview方法,父類變化時,無論是添加到父視圖還是移除父視圖都會調用;在添加時willMoveToSuperview的newSuperview即爲要將要添加的父視圖,此時視圖的superview爲nil,當執行didMoveToSuperview時,視圖的父視圖不再爲nil,爲剛添加的newSuperview;移除時willMoveToSuperview的newSuperview爲nil,didMoveToSuperview時,視圖的父視圖也爲nil;
- willMoveToWindow和didMoveToWindow方法,是持有的window變化時調用,無論是添加 到窗口顯示還是移除窗口消失銷燬都會調用;當添加時willMoveToWindow的newWindow參數不爲nil,self.window卻爲nil,didMoveToWindow的self.window即爲newWindow;移除時willMoveToWindow的newWindow參數爲nil,didMoveToWindow的self.window也爲nil
- 也就是說在添加到父視圖時會在willMoveToSuperview方法中將視圖添加到父視圖中,在willMoveToWindow添加到window中才能展示,而在移除時在willMoveToWindow將當前持有的window置nil,再在willMoveToSuperview中將父視圖置nil;
UIViewController和UIView進入展示時整體生命週期調用順序
self.view是控制器的默認視圖,NoXibView是添加到self.view的子視圖,UIViewController和UIView加載展示時整體生命週期調用順序如下(紅色爲打印的生命週期方法,藍色的爲superview和window):
- vc(控制器)的viewDidLoad方法;
- NoXibView的willMoveToSuperview和didMoveToSuperview,此時已將NoXibView添加到父視圖上;
- vc的viewWillDisappear方法,促使vc的view的superview和window還是爲nil;
- NoXibView的willMoveToWindow和didMoveToWindow,此時已將NoXibView添加到widonw;
- vc的viewWillLayoutSubviews ,此時vc的view的superview和window不再爲nil;
- vc的viewDidLayoutSubviews ;
- NoXibView的layoutSubviews;
- vc的viewDidAppear .
UIViewController和UIView消失銷燬時整體生命週期調用順序如下:
- vc的viewWillDisappear;
- NoXibView的willMoveToWindow,didMoveToWindow,此時NoXibView的window置nil;
- vc的viewDidDisappear;此時vc的view的window和superview都置爲nil;
- vc的’dealloc’;
- NoXibView的willMoveToSuperview和didMoveToSuperview,此時NoXibView的superview置nil;
- NoXibView的removeFromSuperview;
- NoXibView的’dealloc’;
- NoXibView的’willRemoveSubview’.
總結
總而言之加載展示時:就是先將子控件添加到當前控件中,再將子控件添加到window,然後將當前控件添加到父控件中,再將當前控件添加到window中;移除銷燬時:將當前空前的window置nil,再將父控件置nil,將當前控件移除銷燬,再將子控件的window置nil,子控件的父控件置nil;(展示時先添加子控件再添加當前控件再添加父控件,移除時先移除父控件,再移除當前控件,再移除子控件).
開發技巧總結
- 在開發中很多方法是用不到的,所以也沒必要都記順序,上面之所以要打印superview和window,是因爲不管是autoresize還是autolayout佈局都是基於父視圖的,wiondw是最終的顯示載體;
- 對於UIViewController,viewDidLoad:方法是視圖加載完成,我們可以在裏面添加子視圖,設置相關屬性和佈局等,所有和self.view相關的操作在該方法中添加比較合適;viewWillAppear:視圖即將顯示時調用;viewWillLayoutSubviews:視圖將要佈局其子視圖時被調用;viewDidLayoutSubviews:視圖佈局完成其子視圖時被調用;viewDidAppear視圖顯示後被調用;viewWillDisappear:視圖將要消失時調用;viewDidDisappear:視圖已經消失時調用;
- 注意:viewWillAppear:和viewWillDisappear:有時要成對使用;viewDidAppear和viewDidDisappear:有時要成對使用,比如顯示該頁面定位,消失時結束定位;還比如該頁面顯示時影藏導航,去其他頁面時恢復導航;
UIView的layoutSubviews會被經常調用,下面說下layoutsubview的調用情況:
1 addSubview會觸發layoutSubviews,如果addSubview 如果連續2個 只會執行一次,具體原因下面說。
2 設置view的Frame會觸發layoutSubviews,必須是frame的值設置前後發生了變化。
3 滾動一個UIScrollView會觸發layoutSubviews。
4 旋轉Screen會觸發父UIView上的layoutSubviews事件。
5 、改變一個UIView大小的時候也會觸發父UIView上的layoutSubviews事件。