App的生命週期

sauce_xxoo發表於2017-12-17

iOS程式的啟動執行順序

程式啟動順序圖

iOS啟動原理圖

具體執行流程

- (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:]
複製程式碼

記憶體警告

-[AppDelegate applicationDidReceiveMemoryWarning:]
複製程式碼

UIViewController 的生命週期

// 非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];
}

// 出現記憶體警告 
- (void)didReceiveMemoryWarning {
    NSLog(@"%s", __FUNCTION__);
    [super didReceiveMemoryWarning];
}

// 檢視被銷燬
- (void)dealloc {
    NSLog(@"%s", __FUNCTION__);
}
複製程式碼

分析

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

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

  • awakeFromNibawakeFromNib方法被呼叫時,所有檢視的outletaction已經連線,但還沒有被確定,這個方法可以算作適合檢視控制器的例項化配合一起使用的,因為有些需要根據使用者喜好來進行設定的內容,無法存在storyBoardxib中,所以可以在awakeFromNib方法中被載入進來。

  • loadView 當執行到loadView方法時,如果檢視控制器是通過nib建立,那麼檢視控制器已經從nib檔案中被解檔並建立好了,接下來任務就是對view進行初始化。 loadView方法在UIViewController物件的view被訪問且為空的時候呼叫。這是它與awakeFromNib方法的一個區別。 假設我們在處理記憶體警告時釋放view屬性:self.view = nil。因此loadView方法在檢視控制器的生命週期內可能被呼叫多次。 loadView方法不應該直接被呼叫,而是由系統呼叫,它會載入或建立一個view並把它賦值給UIViewControllerview屬性。 在建立view的過程中,首先會根據nibName去找對應的nib檔案然後載入。如果nibName為空或找不到對應的nib檔案,則會建立一個空檢視(這種情況一般是純程式碼) 注意:在重寫loadView方法的時候,不要呼叫父類的方法。

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

  • viewWillAppear 系統在載入所有的資料後,將會在螢幕上顯示檢視,這時會先呼叫這個方法,通常我們會在這個方法對即將顯示的檢視做進一步的設定。比如,設定裝置不同方向時該如何顯示;設定狀態列方向、設定檢視顯示樣式等。 另一方面,當APP有多個檢視時,上下級檢視切換是也會呼叫這個方法,如果在調入檢視時,需要對資料做更新,就只能在這個方法內實現。

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

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

  • viewDidAppearview被新增到檢視層級中以及多檢視,上下級檢視切換時呼叫這個方法,在這裡可以對正在顯示的檢視做進一步的設定。

  • viewWillDisappear 在檢視切換時,當前檢視在即將被移除、或被覆蓋是,會呼叫該方法,此時還沒有呼叫removeFromSuperview

  • viewDidDisappear view已經消失或被覆蓋,此時已經呼叫removeFromSuperView;

  • dealloc 檢視被銷燬,此次需要對你在initviewDidLoad中建立的物件進行釋放。

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

相關文章