UIView的生命週期二

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;(展示時先添加子控件再添加當前控件再添加父控件,移除時先移除父控件,再移除當前控件,再移除子控件).

開發技巧總結

  1. 在開發中很多方法是用不到的,所以也沒必要都記順序,上面之所以要打印superview和window,是因爲不管是autoresize還是autolayout佈局都是基於父視圖的,wiondw是最終的顯示載體;
  2. 對於UIViewController,viewDidLoad:方法是視圖加載完成,我們可以在裏面添加子視圖,設置相關屬性和佈局等,所有和self.view相關的操作在該方法中添加比較合適;viewWillAppear:視圖即將顯示時調用;viewWillLayoutSubviews:視圖將要佈局其子視圖時被調用;viewDidLayoutSubviews:視圖佈局完成其子視圖時被調用;viewDidAppear視圖顯示後被調用;viewWillDisappear:視圖將要消失時調用;viewDidDisappear:視圖已經消失時調用;
  3. 注意: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事件。

如果要立即執行layoutsubview ,要先調用[view setNeedsLayout],把標記設爲需要佈局,然後馬上調用[view layoutIfNeeded],實現佈局.其中的原理是:執行setNeedsLayout後會在receiver標上一個需要被重新佈局的標記,在系統runloop的下一個週期自動調用layoutSubviews。這樣刷新會產生延遲,所以我們需要馬上執行layoutIfNeeded。就會開始遍歷subviews的鏈,判斷該receiver是否需要layout。如果需要立即執行layoutsubview.
每一個視圖只能有唯一的一個父視圖。如果當前操作視圖已經有另外的一個父視圖,則addsubview的操作會把它先從上一個父視圖中移除(包括響應者鏈),再加到新的父視圖上面。
並且連續2次的addSubview,只會執行一次layoutsubview。因爲一次的runLoop結束後,如果有需要刷新,執行一次即可

iOS UIViewController和UIView的生命週期

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章