前言:
所有的移動操作系統(tǒng)都有個致命的缺點:app很容易受到打擾。比如一個來電或者鎖屏?xí)?dǎo)致app進入后臺甚至被終止
還有很多其它類似的情況會導(dǎo)致app受到干擾废离,在app受到干擾時铺根,會產(chǎn)生一些系統(tǒng)事件菠发,這時UIApplication會通知它的delegate對象纳决,讓delegate代理來處理這些系統(tǒng)事件
delegate可處理的事件包括:
- 應(yīng)用程序的生命周期事件(如程序啟動和關(guān)閉) - 系統(tǒng)事件(如來電) - 內(nèi)存警告
- …
應(yīng)用的生命周期--->啟動過程:
這些UIApplicationDelegate,監(jiān)聽?wèi)?yīng)用程序的生命周期,監(jiān)聽內(nèi)存警告,系統(tǒng)事件當(dāng)應(yīng)用程序啟動完畢的時候就會調(diào)用 (系統(tǒng)自動調(diào)用)
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"%s",__func__); return YES; }
即將失去活動狀態(tài)的時候調(diào)用(失去焦點, 不可交互)
- (void)applicationWillResignActive:(UIApplication *)application { NSLog(@"%s",__func__); }
應(yīng)用程序即將進入前臺的時候調(diào)用(一般在該方法中恢復(fù)應(yīng)用程序的數(shù)據(jù),以及狀態(tài))
- (void)applicationWillEnterForeground:(UIApplication *)application > { NSLog(@"%s",__func__); }
應(yīng)用程序進入后臺的時候調(diào)用 (一般在該方法中保存應(yīng)用程序的數(shù)據(jù), 以及狀態(tài))
- (void)applicationDidEnterBackground:(UIApplication *)application { NSLog(@"Background"); }
重新獲取焦點(能夠和用戶交互)
- (void)applicationDidBecomeActive:(UIApplication *)application { NSLog(@"%s",__func__); }
應(yīng)用程序即將被銷毀的時候會調(diào)用該方法
注意:如果應(yīng)用程序處于掛起狀態(tài)的時候無法調(diào)用該方法- (void)applicationWillTerminate:(UIApplication *)application { }
應(yīng)用程序接收到內(nèi)存警告的時候就會調(diào)用
一般在該方法中釋放掉不需要的內(nèi)存- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { NSLog(@"%s",__func__); }
應(yīng)用程序一般有五個狀態(tài):官方文檔app.states
程序啟動生命周期:--> (啟動過程)
~~A篇:啟動原理 ~~
① 執(zhí)行main 函數(shù),調(diào)用 main 函數(shù)里的 UIApplicationMain 函數(shù)凸椿。 intUIApplicationMain(int argc, char argv[], NSString principalClassName, NSString *delegateClassName); argc游沿、argv:直接傳遞給UIApplicationMain進行相關(guān)處理即可 principalClassName:指定應(yīng)用程序類名(app的象征)饰抒,該類必須是UIApplication(或子類)。如果為nil,則用UIApplication類作為默認(rèn)值 delegateClassName:指定應(yīng)用程序的代理類诀黍,該類必須遵守 UIApplicationDelegate協(xié)議 ② UIApplicationMain函數(shù)會根據(jù)principalClassName創(chuàng)建UIApplication對象袋坑, 根據(jù)delegateClassName創(chuàng)建一個delegate對象,并將該delegate對象賦值給 UIApplication對象中的delegate屬性 ③ 接著會建立應(yīng)用程序的Main Runloop(事件循環(huán))眯勾,進行事件的處理(首先會在 程序完畢后調(diào)用delegate對象的application:didFinishLaunchingWithOptions:方法) ④ 程序正常退出時UIApplicationMain函數(shù)才返回 - **系統(tǒng)入口的代碼和參數(shù)說明:** argc:系統(tǒng)或者用戶傳入的參數(shù) argv:系統(tǒng)或用戶傳入的實際參數(shù) 1.根據(jù)傳入的第三個參數(shù)枣宫,創(chuàng)建UIApplication對象 2.根據(jù)傳入的第四個產(chǎn)生創(chuàng)建UIApplication對象的代理 3.設(shè)置剛剛創(chuàng)建出來的代理對象為UIApplication的代理 4.開啟一個事件循環(huán)(可以理解為里面是一個死循環(huán))這個時間循環(huán)是一個隊列(先進先出)先添加進去的先處理
B篇:(完整啟動過程)1.執(zhí)行main 函數(shù),調(diào)用 main 函數(shù)里的 UIApplicationMain 函數(shù)。
2.創(chuàng)建UIApplication
① 打開網(wǎng)頁吃环,發(fā)短信也颤,打電話 ② 設(shè)置應(yīng)用程序提醒數(shù)字 ③ 設(shè)置聯(lián)網(wǎng)狀態(tài) ④ 設(shè)置狀態(tài)欄
3.創(chuàng)建AppDelegate代理對象,并且成為AppDelegate代理
① 監(jiān)聽整個App的生命周期 ② 處理內(nèi)存警告
4.開啟主運循環(huán)郁轻,保證程序一直運行
① 每一個線程都有runloop ② 主線程有一個runloop
5.加載info.plist (判斷是否加載了main.storyboard)
情況1:--> 如果指定(沒有storyboard)
就會在application:didFinishLaunchingWithOptions:中① 創(chuàng)建窗口 ② 設(shè)置根控制器 ③ 顯示窗口
情況2:--> 如果加載的Info.plist文件里的Main storyboard:
系統(tǒng)會自動調(diào)用 (不用我們管)① 創(chuàng)建窗口 ② 加載main.storyboard歇拆,并且加載main.storyboard指定的控制器 ③ 把新創(chuàng)建的控制器,作為窗口的根控制器范咨,讓窗口顯示出來
如圖:
視圖的生命周期--->view
- 1故觅、 alloc 創(chuàng)建對象,分配空間 - 2渠啊、 init (initWithNibName) 初始化對象输吏,初始化數(shù)據(jù) - 3、 loadView 從nib載入視圖 替蛉,除非你沒有使用xib文件創(chuàng)建視圖 - 4贯溅、 viewDidLoad 載入完成,可以進行自定義數(shù)據(jù)以及動態(tài)創(chuàng)建其他控件 - 5躲查、 viewWillAppear視圖將出現(xiàn)在屏幕之前它浅,馬上這個視圖就會被展現(xiàn)在屏幕上了 - 6、 viewDidAppear 視圖已在屏幕上渲染完成 - 7镣煮、viewWillDisappear 視圖將被從屏幕上移除之前執(zhí)行 - 8姐霍、viewDidDisappear 視圖已經(jīng)被從屏幕上移除,用戶看不到這個視圖了 - 9、dealloc 視圖被銷毀镊折,此處需要對你在init和viewDidLoad中創(chuàng)建的對象進行釋放. - 10胯府、viewVillUnload- 當(dāng)內(nèi)存過低,即將釋放時調(diào)用恨胚; - 11骂因、viewDidUnload-當(dāng)內(nèi)存過低,釋放一些不需要的視圖時調(diào)用赃泡。