iOS應用程序的狀態切換很重要,而UIViewControler對於iOS這種MVC模式來講尤其重要,基本都要繼承自他。微信
1、iOS程序的啓動執行順序app
1 程序的入口ide
進入main函數, 設置AppDelegate稱爲函數的代理函數
2 程序完成加載ui
-[AppDelegate application:didFinishLaunchingWithOptions:]this
3 建立window窗口spa
4 程序被激活翻譯
-[AppDelegate applicationDidBecomeActive:]代理
5 當點擊command+H時指針
程序取消激活狀態
-[AppDelegate applicationWillResignActive:]
程序進入後臺
-[AppDelegate applicationDidEnterBackground:]
6 點擊進入工程
程序進入前臺
-[AppDelegate applicationWillEnterForeground:]
程序被激活
-[AppDelegate applicationDidBecomeActive:]
(1)applicationWillResignActive(非活動):
好比當有電話進來或短信進來,在或者鎖屏等,這時你的應用程序掛起進入非活動狀態,也就是你的手機其實界面仍是顯示着你當前的App窗口,只不過被別的任務強制佔用了,或者後臺狀態(由於要先進入非活動狀態,而後進入後臺)。
(2)applicationDidEnterBackground(後臺):
指當前窗口不是你的App,大多數程序進入這個後臺後會在在這個狀態上停留一會,時間到以後會進入掛起狀態(Suspended)。若是你程序特殊處理後能夠長期處於後臺狀態即在後臺狀態也能夠運行。Suspended(掛起):程序在後臺不能執行代碼。系統會自動把程序變成這個狀態並且不會發出通知。當掛起時,程序仍是停留在內存中的,當系統內存低時,系統就把掛起的程序清除掉,爲前臺程序提供更多的內存。
看下面流程圖:
這個圖特別重要,說明了全部的切換狀態。
入口函數:
int main(int argc, char * argv[]) { @autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([XYZAppDelegate class]));
} }
2.UIApplicationMain 函數解釋:
官方解釋
// If nil is specified for principalClassName, the value for NSPrincipalClass from the Info.plist is used. If there is no // NSPrincipalClass key specified, the UIApplication class is used. The delegate class will be instantiated using init. UIKIT_EXTERN int UIApplicationMain(int argc, char *argv[], NSString *principalClassName, NSString *delegateClassName);
翻譯過來以後(參數的解釋)
1.argc和argv參數是爲了與C語言保持一致,在這沒用到,不詳述。
2.後面兩個參數爲principalClassName(主要類名)和delegateClassName(委託類名)。
(1)若是principalClassName是nil,那麼它的值將從Info.plist中獲取,若是Info.plist中沒有,則默認爲UIApplication。principalClass這個類除了管理整個程序的生命週期以外什麼都不作,它只負責監聽事件而後交給delegateClass去作。
(2)delegateClass將在工程新建時實例化一個對象。NSStringFromClass([AppDelegate class]) //至關於@"AppDelegate"
3.AppDelegate類實現文件
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOption{// Override point for customization after application launch. NSLog(@"didFinishLaunchingWithOptions"); return YES; } - (void)applicationWillResignActive:(UIApplication *)application { /* 當應用程序從活動狀態(active)變到非活動狀態(inactive時被觸發調用, 這可能發生在一些臨時中斷下(例如:來電話、來短信)又或者程序退出時,他會先過渡到後臺而後terminate 使用這方法去暫停正在進行的任務,禁用計時器,節流OpenGL ES 幀率。在遊戲中應該在這個方法裏面暫停遊戲。 */ // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. NSLog(@"WillResignActive"); } - (void)applicationDidEnterBackground:(UIApplication *)application { /* 使用這種方法來釋放共享資源,保存用戶數據,無效計時器,存儲足夠多的應用程序狀態信息來恢復您的應用程序的當前狀態,以防它終止丟失數據。 若是你的程序支持後臺運行,那麼當用戶退出時不會調用applicationWillTerminate。 */ // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. NSLog(@"DidEnterBackground"); } - (void)applicationWillEnterForeground:(UIApplication *)application { /* 先從後臺切換到非活動狀態,而後進入活動狀態。 */ // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. NSLog(@"WillEnterForeground"); } - (void)applicationDidBecomeActive:(UIApplication *)application { /* 重啓全部的任務,不論是從非活動狀態仍是剛啓動程序,仍是後臺狀態。 */ // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. NSLog(@"DidBecomeActive"); } - (void)applicationWillTerminate:(UIApplication *)application { /* 終止,game over */ // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. NSLog(@"WillTerminate"); }
下面給出打印就明白他們之間的交互前後順序了:
啓動程序
2014-07-28 15:22:39.883 LifeCycle[3024:a0b] didFinishLaunchingWithOptions
2014-07-28 15:22:39.887 LifeCycle[3024:a0b] DidBecomeActive
按下Home鍵
2014-07-28 15:22:43.130 LifeCycle[3024:a0b] WillResignActive
2014-07-28 15:22:43.131 LifeCycle[3024:a0b] DidEnterBackground
從新點擊程序
2014-07-28 15:22:44.380 LifeCycle[3024:a0b] WillEnterForeground
2014-07-28 15:22:44.380 LifeCycle[3024:a0b] DidBecomeActive
分析:
1.application:didFinishLaunchingWithOptions:
程序首次已經完成啓動時執行,若直接啓動,launchOptions中沒有數據;不然,launchOptions將包含對應方式的內容(好比從微信中啓動節奏大師--)。
2.applicationWillResignActive(非活動)
程序將要失去Active狀態時調用,好比按下Home鍵或有電話信息進來。以後程序將進入後臺狀態。對應的applicationWillEnterForeground這個方法用來
a、暫停正在執行的任務;
b、禁止計時器;
c、減小OpenGL ES幀率;
d、若爲遊戲應暫停遊戲;
3.applicationDidEnterBackground(已經進入後臺)
程序已經進入後臺時調用,對應applicationDidBecomeActive(已經變成前臺),這個方法用來
a、釋放共享資源;
b、保存用戶數據(寫到硬盤);
c、做廢計時器;
d、保存足夠的程序狀態以便下次恢復;
4.applicationWillEnterForeground(將進入前臺)
程序即將進去前臺時調用,對應applicationWillResignActive(將進入後臺)。這個方法用來
1.撤銷applicationWillResignActive中作的改變。
5.applicationDidBecomeActive(已經進入前臺)
程序已經變爲Active(前臺)時調用。對應applicationDidEnterBackground(已經進入後臺)。
1.若程序以前在後臺,在此方法內刷新用戶界面。
6.applicationWillTerminate
程序即將退出時調用。記得保存數據,如applicationDidEnterBackground方法同樣。
其實仔細看上面那個狀態圖和輸出打印,他說明了全部這些切換交互流程。
2、UIViewController的生命週期
//The designated initializer //這個UIViewController的指定初始化方法(其餘的初始化方法最終要調用這個初始化方法); //若是鏈接了串聯圖storyBoard根本就不用管這貨 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { NSLog(@"%s", __FUNCTION__); self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } //視圖控制器中的視圖加載完成,viewController自帶的view加載完成 - (void)viewDidLoad { NSLog(@"%s", __FUNCTION__); [super viewDidLoad]; // Do any additional setup after loading the view. } //出現內存警告 //模擬內存警告:點擊模擬器->hardware-> Simulate Memory Warning - (void)didReceiveMemoryWarning { NSLog(@"%s", __FUNCTION__); [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } //視圖將要出現 - (void)viewWillAppear:(BOOL)animated { NSLog(@"%s", __FUNCTION__); [super viewWillAppear:animated]; } //視圖已經出現 - (void)viewDidAppear:(BOOL)animated { NSLog(@"%s", __FUNCTION__); [super viewDidAppear:animated]; } //視圖將要消失 //雙擊Home鍵,向上推出程序執行該函數 - (void)viewWillDisappear:(BOOL)animated { NSLog(@"%s", __FUNCTION__); [super viewWillDisappear:animated]; } //視圖已經消失 - (void)viewDidDisappear:(BOOL)animated { NSLog(@"%s", __FUNCTION__); [super viewDidDisappear:animated]; } @end
看打印輸出:
2015-01-03 17:39:03.973 LessonUIViewControler[791:41458] -[RootViewController initWithNibName:bundle:]
2015-01-03 17:39:03.976 LessonUIViewControler[791:41458] -[RootViewController viewDidLoad]
2015-01-03 17:39:03.976 LessonUIViewControler[791:41458] -[RootViewController viewWillAppear:]
2015-01-03 17:39:04.071 LessonUIViewControler[791:41458] -[RootViewController viewDidAppear:]
2015-01-03 17:39:11.630 LessonUIViewControler[791:41458] Received memory warning.
2015-01-03 17:39:11.631 LessonUIViewControler[791:41458] -[RootViewController didReceiveMemoryWarning]
2015-01-03 17:39:17.581 LessonUIViewControler[791:41458] -[RootViewController viewWillDisappear:]
2015-01-03 17:39:17.581 LessonUIViewControler[791:41458] -[RootViewController viewDidDisappear:]
當一個視圖控制器被建立,並在屏幕上顯示的時候。 代碼的執行順序
一、alloc 建立對象,分配空間;
二、init (initWithNibName) 初始化對象,初始化數據;
三、loadView 從nib載入視圖 ,一般這一步不須要去幹涉。除非你沒有使用xib文件建立視圖;
四、viewDidLoad 載入完成,能夠進行自定義數據以及動態建立其餘控件;
五、viewWillAppear 視圖將出如今屏幕以前,立刻這個視圖就會被展示在屏幕上了;
六、viewDidAppear 視圖已在屏幕上渲染完成 當一個視圖被移除屏幕而且銷燬的時候的執行順序,這個順序差很少和上面的相反;
一、viewWillDisappear
視圖將被從屏幕上移除以前執行
二、viewDidDisappear
視圖已經被從屏幕上移除,用戶看不到這個視圖了
三、dealloc
視圖被銷燬,此處須要對你在init和viewDidLoad中建立的對象進行釋放 關於viewDidUnload :在發生內存警告的時候若是本視圖不是當前屏幕上
正在顯示的視圖的話,
viewDidUnload將會被執行,本視圖的全部子視圖將被銷燬,以釋放內存,此時開發者須要手動對viewLoad、viewDidLoad中建立 的對象釋放內存。
由於當這個視圖再次顯示在屏幕上的時候,viewLoad、viewDidLoad 再次被調用,以便再次構造視圖。 當咱們建立一個UIViewController類的對
象時,一般系統會生成幾個默認的方法,這些方法大多與視圖的調用有關,可是在視圖調用時,這些方法的調用順序如何,須要整理下。 一般上
述方法包括以下幾種,這些方法都是UIViewController類的方法:
- (void)viewDidLoad;
- (void)viewDidUnload;
- (void)viewWillAppear:(BOOL)animated;
- (void)viewDidAppear:(BOOL)animated;
- (void)viewWillDisappear:(BOOL)animated;
- (void)viewDidDisappear:(BOOL)animated;
下面介紹下APP在運行時的調用順序。
1)- (void)viewDidLoad; 一個APP在載入時會先經過調用loadView方法或者載入IB中建立的初始界面的方法,將視圖載入到內存中。而後會
調用viewDidLoad方法來進行進一步的設置。一般,咱們對於各類初始數據的載入,初始設定等不少內容,都會在這個方法中實現,因此這個方法是
一個很經常使用,很重要的方法。
可是要注意,這個方法只會在APP剛開始加載的時候調用一次,之後都不會再調用它了,因此只能用來作初始設置。
2) - (void)viewDidUnload;在內存足夠的狀況下,軟件的視圖一般會一直保存在內存中,可是若是內存不夠,一些沒有正在顯示的viewcontroller就
會收到內存不夠的警告,然 後就會釋放本身擁有的視圖,以達到釋放內存的目的。可是系統只會釋放內存,並不會釋放對象的全部權,因此一般咱們
須要在這裏將不須要在內存中保留的對象釋 放全部權,也就是將其指針置爲nil。 這個方法一般並不會在視圖變換的時候被調用,而只會在系
統退出或者收到內存警告的時候纔會被調用。可是因爲咱們須要保證在收到內存警告的時候可以對其做出反應,因此這個方法一般咱們都須要去實現。
另外,即便在設備上按了Home鍵以後,系統也不必定會調用這個方法,由於IOS4以後,系統容許將APP在後臺掛起,並將其繼續滯留在內存中,所以,
viewcontroller並不會調用這個方法來清除內存。
3)- (void)viewWillAppear:(BOOL)animated;系統在載入全部數據後,將會在屏幕上顯示視圖,這時會先調用這個方法。一般咱們會利用這個方法,
對即將顯示的視圖作進一步的設置。例如,咱們能夠利用這個方法來設置設備不一樣方向時該如何顯示。 另一方面,當APP有多個視圖時,在
視圖間切換時,並不會再次載入viewDidLoad方法,因此若是在調入視圖時,須要對數據作更新,就只能在這個方法內實現了。因此這個方法也很是經常使用。
4) - (void)viewDidAppear:(BOOL)animated;
有時候,因爲一些特殊的緣由,咱們不能在viewWillApper方法裏,對視圖進行更新。那麼能夠重寫這個方法,在這裏對正在顯示的視圖進行進一步的設置。
5) - (void)viewWillDisappear:(BOOL)animated;
在視圖變換時,當前視圖在即將被移除、或者被覆蓋時,會調用這個方法進行一些善後的處理和設置。
因爲在IOS4以後,系統容許將APP在後臺掛起,因此在按了Home鍵以後,系統並不會調用這個方法,由於就這個APP自己而言,APP顯示的view,還是掛起時候
的view,因此並不會調用這個方法。
6) - (void)viewDidDisappear:(BOOL)animated;
咱們能夠重寫這個方法,對已經消失,或者被覆蓋,或者已經隱藏了的視圖作一些其餘操做。 上述方法的流程圖能夠簡單用以下表示:
運行APP —> 載入視圖 —> 調用viewDidLoad方法 —> 調用viewWillAppear方法 —> 調用viewDidAppear方法 —> 正常運行