iOS程式執行順序和UIViewController 的生命週期(整理)

來源:互聯網
上載者:User

標籤:life   win   com   ted   rip   3.3   jpeg   blog   控制器   

說明:此文是自己的總結筆記,主要參考:iOS程式的啟動執行順序 AppDelegate 及 UIViewController 的生命週期UIView的生命週期

言葉之庭.jpeg一. iOS程式的啟動執行順序

程式啟動順序圖


iOS啟動原理圖.png

具體執行流程

  1. 程式入口
    進入main函數,設定AppDelegate稱為函數的代理

  2. 程式完成載入
    [AppDelegate application:didFinishLaunchingWithOptions:]

  3. 建立window視窗

  4. 程式被啟用
    [AppDelegate applicationDidBecomeActive:]

  5. 當點擊command+H時(針對模擬器,手機是當點擊home鍵)
    程式取消啟用狀態
    [AppDelegate applicationWillResignActive:];
    程式進入後台
    [AppDelegate applicationDidEnterBackground:];

  6. 點擊進入工程
    程式進入前台
    [AppDelegate applicationWillEnterForeground:]
    程式被啟用
    [AppDelegate applicationDidBecomeActive:];

分析

1. 對於applicationWillResignActive(非活動)applicationDidEnterBackground(後台)這兩個的區別。

  • applicationWillResignActive(非活動):
    比如當有電話進來或簡訊進來或鎖屏等情況下,這時應用程式掛起進入非使用中,也就是手機介面還是顯示著你當前的應用程式的視窗,只不過被別的任務強制佔用了,也可能是即將進入後台狀態(因為要先進入非使用中然後進入後台狀態)

  • applicationDidEnterBackground(後台):
    指當前視窗不是你的App,大多數程式進入這個後台會在這個狀態上停留一會,時間到之後會進入掛起狀態(Suspended)。如果你程式特殊處理後可以長期處於後台狀態也可以運行。
    Suspended (掛起): 程式在後台不能執行代碼。系統會自動把程式變成這個狀態而且不會發出通知。當掛起時,程式還是停留在記憶體中的,當系統記憶體低時,系統就把掛起的程式清除掉,為前景程式提供更多的記憶體。

如所示:


活動和非活動.png

2.UIApplicationMain 函數解釋:

入口函數:

int main(int argc, char * argv[]) {        @autoreleasepool {            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));        } } UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
  • argc argv 參數是為了與C語言保持一致。

  • principalClassName (主要類名) delegateClassName (委託類名)
    (1) 如果principalClassName是nil,那麼它的值將從Info.plist去擷取,如果Info.plist沒有,則預設為UIApplicationprincipalClass這個類除了管理整個程式的生命週期之外什麼都不做,它只負責監聽事件然後交給delegateClass去做。
    (2) delegateClass 將在工程建立時執行個體化一個對象。NSStringFromClass([AppDelegate class])

  • AppDelegate 類實現檔案

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    NSLog(@"--- %s ---",__func__);//__func__列印方法名    return YES;}- (void)applicationWillResignActive:(UIApplication *)application {     NSLog(@"--- %s ---",__func__);}- (void)applicationDidEnterBackground:(UIApplication *)application {   NSLog(@"--- %s ---",__func__);}- (void)applicationWillEnterForeground:(UIApplication *)application {   NSLog(@"--- %s ---",__func__);}- (void)applicationDidBecomeActive:(UIApplication *)application {  NSLog(@"--- %s ---",__func__);}- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {     NSLog(@"--- %s ---",__func__);}- (void)applicationWillTerminate:(UIApplication *)application {    NSLog(@"--- %s ---",__func__);}

列印調用順序
啟動程式

 --- -[AppDelegate application:didFinishLaunchingWithOptions:] --- --- -[AppDelegate applicationDidBecomeActive:] ---

按下 Command + H + SHIFT

--- -[AppDelegate applicationWillResignActive:] ------ -[AppDelegate applicationDidEnterBackground:] ---

重新點擊 進入程式

--- -[AppDelegate applicationWillEnterForeground:] ------ -[AppDelegate applicationDidBecomeActive:] ---

選擇 模擬器的Simulate Memory Warning

--- -[AppDelegate applicationDidReceiveMemoryWarning:] ---

分析:

1.application:didFinishLaunchingWithOptions:
程式首次已經完成啟動時執行,一般在這個函數裡建立window對象,將程式內容通過window呈現給使用者。

  1. applicationWillResignActive(非活動)
    程式將要失去Active狀態時調用,比如有電話進來或者按下Home鍵,之後程式進入後台狀態,對應的applicationWillEnterForeground(即將進入前台)方法。

    該函數裡面主要執行操作:
    a . 暫停正在執行的任務
    b. 禁止計時器
    c. 減少OpenGL ES幀率
    d. 若為遊戲應暫停遊戲

3.applicationDidEnterBackground(已經進入後台)
對應applicationDidBecomeActive(已經變成前台)

該方法用來:
a. 釋放共用資源
b. 儲存使用者資料(寫到硬碟)
c. 作廢計時器
d. 儲存足夠的程式狀態以便下次修複;

  1. applicationWillEnterForeground(即將進入前台)
    程式即將進入前台時調用,對應applicationWillResignActive(即將進入後台)
    這個方法用來: 撤銷applicationWillResignActive中做的改變。

  2. applicationDidBecomeActive(已經進入前台)
    程式已經變為Active(前台)時調用。對應applicationDidEnterBackground(已經進入後台)
    注意: 若程式之前在後台,在此方法內重新整理使用者介面

  3. applicationWillTerminate
    程式即將退出時調用。記得儲存資料,如applicationDidEnterBackground方法一樣。


等候.jpeg二. UIViewController 的 生命週期

代碼 樣本

#pragma mark --- life circle// 非storyBoard(xib或非xib)都走這個方法- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {    NSLog(@"%s", __FUNCTION__);    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {    }    return self;}// 如果串連了串聯圖storyBoard 走這個方法- (instancetype)initWithCoder:(NSCoder *)aDecoder {     NSLog(@"%s", __FUNCTION__);    if (self = [super initWithCoder:aDecoder]) {    }    return self;}// xib 載入 完成- (void)awakeFromNib {    [super awakeFromNib];     NSLog(@"%s", __FUNCTION__);}// 載入視圖(預設從nib)- (void)loadView {    NSLog(@"%s", __FUNCTION__);    self.view = [[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];    self.view.backgroundColor = [UIColor redColor];}//視圖控制器中的視圖載入完成,viewController內建的view載入完成- (void)viewDidLoad {    NSLog(@"%s", __FUNCTION__);    [super viewDidLoad];}//視圖將要出現- (void)viewWillAppear:(BOOL)animated {    NSLog(@"%s", __FUNCTION__);    [super viewWillAppear:animated];}// view 即將布局其 Subviews- (void)viewWillLayoutSubviews {    NSLog(@"%s", __FUNCTION__);    [super viewWillLayoutSubviews];}// view 已經布局其 Subviews- (void)viewDidLayoutSubviews {    NSLog(@"%s", __FUNCTION__);    [super viewDidLayoutSubviews];}//視圖已經出現- (void)viewDidAppear:(BOOL)animated {    NSLog(@"%s", __FUNCTION__);    [super viewDidAppear:animated];}//視圖將要消失- (void)viewWillDisappear:(BOOL)animated {    NSLog(@"%s", __FUNCTION__);    [super viewWillDisappear:animated];}//視圖已經消失- (void)viewDidDisappear:(BOOL)animated {    NSLog(@"%s", __FUNCTION__);    [super viewDidDisappear:animated];}//出現記憶體警告  //類比記憶體警告:點擊模擬器->hardware-> Simulate Memory Warning- (void)didReceiveMemoryWarning {    NSLog(@"%s", __FUNCTION__);    [super didReceiveMemoryWarning];}// 視圖被銷毀- (void)dealloc {    NSLog(@"%s", __FUNCTION__);}

查看 列印 結果

2017-03-01 18:03:41.577 ViewControllerLifeCircle[32254:401790] -[ViewController initWithCoder:]2017-03-01 18:03:41.579 ViewControllerLifeCircle[32254:401790] -[ViewController awakeFromNib]2017-03-01 18:03:41.581 ViewControllerLifeCircle[32254:401790] -[ViewController loadView]2017-03-01 18:03:46.485 ViewControllerLifeCircle[32254:401790] -[ViewController viewDidLoad]2017-03-01 18:03:46.486 ViewControllerLifeCircle[32254:401790] -[ViewController viewWillAppear:]2017-03-01 18:03:46.487 ViewControllerLifeCircle[32254:401790] -[ViewController viewWillLayoutSubviews]2017-03-01 18:03:46.488 ViewControllerLifeCircle[32254:401790] -[ViewController viewDidLayoutSubviews]2017-03-01 18:03:46.488 ViewControllerLifeCircle[32254:401790] -[ViewController viewWillLayoutSubviews]2017-03-01 18:03:46.488 ViewControllerLifeCircle[32254:401790] -[ViewController viewDidLayoutSubviews]2017-03-01 18:03:46.490 ViewControllerLifeCircle[32254:401790] -[ViewController viewDidAppear:]2017-03-01 19:03:13.308 ViewControllerLifeCircle[32611:427962] -[ViewController viewWillDisappear:]2017-03-01 19:03:14.683 ViewControllerLifeCircle[32611:427962] -[ViewController viewDidDisappear:]2017-03-01 19:03:14.683 ViewControllerLifeCircle[32611:427962] -[ViewController dealloc]2017-03-01 19:12:05.927 ViewControllerLifeCircle[32611:427962] -[ViewController didReceiveMemoryWarning]

分析
1.initWithNibName:bundle:
初始化UIViewController,執行關鍵資料初始化操作,非StoryBoard建立UIViewController都會調用這個方法。
注意: 不要在這裡做View相關操作,ViewloadView方法中才初始化。

2. initWithCoder:
如果使用StoryBoard進行視圖管理,程式不會直接初始化一個UIViewControllerStoryBoard會自動初始化或在segue被觸發時自動初始化,因此方法initWithNibName:bundle不會被調用,但是initWithCoder會被調用。

3. awakeFromNib
awakeFromNib方法被調用時,所有視圖的outletaction已經串連,但還沒有被確定,這個方法可以算作適合視圖控制器的執行個體化配合一起使用的,因為有些需要根據使用者洗好來進行設定的內容,無法存在storyBoardxib中,所以可以在awakeFromNib方法中被載入進來。

4. loadView
當執行到loadView方法時,如果視圖控制器是通過nib建立,那麼視圖控制器已經從nib檔案中被解檔並建立好了,接下來任務就是對view進行初始化。

loadView方法在UIViewController對象的view被訪問且為空白的時候調用。這是它與awakeFromNib方法的一個區別。
假設我們在處理記憶體警告時釋放view屬性:self.view = nil。因此loadView方法在視圖控制器的生命週期內可能被調用多次。
loadView方法不應該直接被調用,而是由系統調用。它會載入或建立一個view並把它賦值給UIViewControllerview屬性。

在建立view的過程中,首先會根據nibName去找對應的nib檔案然後載入。如果nibName為空白或找不到對應的nib檔案,則會建立一個空視圖(這種情況一般是純程式碼)

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

5. viewDidLoad
loadViewview載入記憶體中,會進一步調用viewDidLoad方法來進行進一步設定。此時,視圖層次已經放到記憶體中,通常,我們對於各種初始化資料的載入,初始設定、修改約束、移除視圖等很多操作都可以這個方法中實現。

視圖層次(view hierachy):因為每個視圖都有自己的子視圖,這個視圖層次其實也可以理解為一顆樹狀的資料結構。而樹的根節點,也就是根視圖(root view),在UIViewController中以view屬性。它可以看做是其他所有子視圖的容器,也就是根節點。
6. viewWillAppear
系統在載入所有的資料後,將會在螢幕上顯示視圖,這時會先調用這個方法,通常我們會在這個方法對即將顯示的視圖做進一步的設定。比如,設定裝置不同方向時該如何顯示;設定狀態列方向、設定視圖顯示樣式等。

另一方面,當APP有多個視圖時,上下級視圖切換是也會調用這個方法,如果在調入視圖時,需要對資料做更新,就只能在這個方法內實現。

7. viewWillLayoutSubviews
view 即將布局其Subviews。 比如viewbounds改變了(例如:狀態列從不顯示到顯示,視圖方向變化),要調整Subviews的位置,在調整之前要做的工作可以放在該方法中實現

8.viewDidLayoutSubviews
view已經布局其Subviews,這裡可以放置調整完成之後需要做的工作。

9. viewDidAppear
在view被添加到視圖層級中以及多視圖,上下級視圖切換時調用這個方法,在這裡可以對正在顯示的視圖做進一步的設定。

10.viewWillDisappear
在視圖切換時,當前視圖在即將被移除、或被覆蓋是,會調用該方法,此時還沒有調用removeFromSuperview

11. viewDidDisappear
view已經消失或被覆蓋,此時已經調用removeFromSuperView;

12. dealloc
視圖被銷毀,此次需要對你在initviewDidLoad中建立的對象進行釋放。

13.didReceiveMemoryWarning
在記憶體足夠的情況下,app```的視圖通常會一直儲存在記憶體中,但是如果記憶體不夠,一些沒有正在顯示的viewController就會收到記憶體不足的警告,然後就會釋放自己擁有的視圖,以達到釋放記憶體的目的。但是系統只會釋放記憶體,並不會釋放對象的所有權,所以通常我們需要在這裡將不需要顯示在記憶體中保留的對象釋放它的所有權,將其指標置nil``。

三. 視圖的生命曆程
  • [ViewController initWithCoder:][ViewController initWithNibName:Bundle]: 首先從歸檔檔案中載入UIViewController對象。即使是純程式碼,也會把nil作為參數傳給後者。
  • [UIView awakeFromNib]: 作為第一個方法的助手,方法處理一些額外的設定。
  • [ViewController loadView]: 建立或載入一個view並把它賦值給UIViewControllerview屬性。
    -[ViewController viewDidLoad]: 此時整個視圖層次(view hierarchy)已經放到記憶體中,可以移除一些視圖,修改約束,載入資料等。
  • [ViewController viewWillAppear:]: 視圖載入完成,並即將顯示在螢幕上。還沒設定動畫,可以改變當前螢幕方向或狀態列的風格等。
  • [ViewController viewWillLayoutSubviews]即將開始子視圖位置布局
  • [ViewController viewDidLayoutSubviews]用於通知視圖的位置布局已經完成
  • [ViewController viewDidAppear:]視圖已經展示在螢幕上,可以對視圖做一些關於展示效果方面的修改。
  • [ViewController viewWillDisappear:]視圖即將消失
  • [ViewController viewDidDisappear:]視圖已經消失四: 總結:
  • 只有init系列的方法,如initWithNibName需要自己調用,其他方法如loadViewawakeFromNib則是系統自動調用。而viewWill/Did系列的方法則類似於回調和通知,也會被自動調用。

  • 純程式碼寫視圖布局時需要注意,要手動調用loadView方法,而且不要調用父類的loadView方法。純程式碼和用IB的區別僅存在於loadView方法及其之前,編程時需要注意的也就是loadView方法。

  • 除了initWithNibNameawakeFromNib方法是處理視圖控制器外,其他方法都是處理視圖。這兩個方法在視圖控制器的生命週期裡只會調用一次。

     



轉自:http://www.jianshu.com/p/d60b388b19f5

iOS程式執行順序和UIViewController 的生命週期(整理)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.