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
相關操作,View
在loadView
方法中才初始化。 -
initWithCoder:
如果使用StoryBoard
進行檢視管理,程式不會直接初始化一個UIViewController
,StoryBoard
會自動初始化或在segue
被觸發時自動初始化,因此方法initWithNibName:bundle
不會被呼叫,但是initWithCoder
會被呼叫。 -
awakeFromNib
當awakeFromNib
方法被呼叫時,所有檢視的outlet
和action
已經連線,但還沒有被確定,這個方法可以算作適合檢視控制器的例項化配合一起使用的,因為有些需要根據使用者喜好來進行設定的內容,無法存在storyBoard
或xib
中,所以可以在awakeFromNib
方法中被載入進來。 -
loadView
當執行到loadView
方法時,如果檢視控制器是通過nib
建立,那麼檢視控制器已經從nib
檔案中被解檔並建立好了,接下來任務就是對view
進行初始化。loadView
方法在UIViewController
物件的view
被訪問且為空的時候呼叫。這是它與awakeFromNib
方法的一個區別。 假設我們在處理記憶體警告時釋放view
屬性:self.view = nil
。因此loadView
方法在檢視控制器的生命週期內可能被呼叫多次。loadView
方法不應該直接被呼叫,而是由系統呼叫,它會載入或建立一個view
並把它賦值給UIViewController
的view
屬性。 在建立view
的過程中,首先會根據nibName
去找對應的nib
檔案然後載入。如果nibName
為空或找不到對應的nib檔案,則會建立一個空檢視(這種情況一般是純程式碼) 注意:在重寫loadView方法的時候,不要呼叫父類的方法。 -
viewDidLoad
當loadView
將view
載入記憶體中,會進一步呼叫viewDidLoad
方法來進行進一步設定。此時,檢視層次已經放到記憶體中,通常,我們對於各種初始化資料的載入,初始設定、修改約束、移除檢視等很多操作都可以這個方法中實現。 -
viewWillAppear
系統在載入所有的資料後,將會在螢幕上顯示檢視,這時會先呼叫這個方法,通常我們會在這個方法對即將顯示的檢視做進一步的設定。比如,設定裝置不同方向時該如何顯示;設定狀態列方向、設定檢視顯示樣式等。 另一方面,當APP有多個檢視時,上下級檢視切換是也會呼叫這個方法,如果在調入檢視時,需要對資料做更新,就只能在這個方法內實現。 -
viewWillLayoutSubviews
view
即將佈局其Subviews
。 比如view
的bounds
改變了(例如:狀態列從不顯示到顯示,檢視方向變化),要調整Subviews
的位置,在調整之前要做的工作可以放在該方法中實現 -
viewDidLayoutSubviews
view
已經佈局其Subviews
,這裡可以放置調整完成之後需要做的工作。 -
viewDidAppear
在view
被新增到檢視層級中以及多檢視,上下級檢視切換時呼叫這個方法,在這裡可以對正在顯示的檢視做進一步的設定。 -
viewWillDisappear
在檢視切換時,當前檢視在即將被移除、或被覆蓋是,會呼叫該方法,此時還沒有呼叫removeFromSuperview
。 -
viewDidDisappear
view
已經消失或被覆蓋,此時已經呼叫removeFromSuperView
; -
dealloc
檢視被銷燬,此次需要對你在init
和viewDidLoad
中建立的物件進行釋放。 -
didReceiveMemoryWarning
在記憶體足夠的情況下,app的檢視通常會一直儲存在記憶體中,但是如果記憶體不夠,一些沒有正在顯示的viewController就會收到記憶體不足的警告,然後就會釋放自己擁有的檢視,以達到釋放記憶體的目的。但是系統只會釋放記憶體,並不會釋放物件的所有權,所以通常我們需要在這裡將不需要顯示在記憶體中保留的物件釋放它的所有權,將其指標置nil。