在開發(fā)過程中,我們很少真正研究過這個(gè)類辈挂,很多半路出家的程序員對(duì)于view
的生命周期有所了解衬横,但對(duì)UIApplication
未深入研究。在開發(fā)過程中终蒂,相信我們都或多或少的使用了其中的很多功能蜂林,下面就來探討和總結(jié)一下其中的內(nèi)容,又見iOS拇泣,就讓我們從main
開始噪叙,重新進(jìn)入iOS的新世界。
簡(jiǎn)述UIApplication##
UIApplication
的核心作用是提供了iOS程序運(yùn)行期間的控制和協(xié)作工作挫酿。每一個(gè)程序在運(yùn)行期必須有且僅有一個(gè)UIApplication(或則其子類)
的一個(gè)實(shí)例构眯。在程序開始運(yùn)行的時(shí)候,UIApplicationMain
函數(shù)是程序進(jìn)入點(diǎn)早龟,這個(gè)函數(shù)做了很多工作惫霸,其中一個(gè)重要的工作就是創(chuàng)建一個(gè)UIApplication
的單例實(shí)例。在你的代碼中你葱弟,你可以通過調(diào)用[UIApplication sharedApplication]
來得到這個(gè)單例實(shí)例的指針壹店。
UIApplication
的一個(gè)主要工作是處理用戶事件,它會(huì)起一個(gè)隊(duì)列芝加,把所有用戶事件都放入隊(duì)列硅卢,逐個(gè)處理,在處理的時(shí)候藏杖,它會(huì)發(fā)送當(dāng)前事件到一個(gè)合適的處理事件的目標(biāo)控件将塑。此外,UIApplication
實(shí)例還維護(hù)一個(gè)在本應(yīng)用中打開的window
列表(UIWindow實(shí)例
)蝌麸,這樣它就可以接觸應(yīng)用中的任何一個(gè)UIView
對(duì)象点寥。UIApplication
實(shí)例會(huì)被賦予一個(gè)代理對(duì)象,以處理應(yīng)用程序的生命周期事件(比如程序啟動(dòng)和關(guān)閉)来吩、系統(tǒng)事件(比如來電敢辩、記事項(xiàng)警告)等等。
新建一個(gè)任意類型的iOS應(yīng)用工程弟疆,我們可以看到工程中生成一個(gè)類:
AppDelegate :UIResponder <UIApplicationDelegate>
這里這個(gè)類的基類是UIResponder
(注:iOS 4.2以前生成的工程是不同的戚长,以前是繼承自NSObject
)。不論如何怠苔,本類實(shí)現(xiàn)了一個(gè)名叫UIApplicationDelegate
的接口同廉,這個(gè)表明這個(gè)類就是這個(gè)工程中UIApplication
實(shí)例的代理類。
在main
函數(shù)中,
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
這里傳入了代理類到UIApplicationMain
函數(shù)中恤溶,UIApplicationMain
函數(shù)在生成唯一個(gè)UIApplication
的時(shí)候就可以把代理類的實(shí)例指針告訴這個(gè)單例對(duì)象了乓诽。
[注]參數(shù)說明
argc
:系統(tǒng)或者用戶傳入的參數(shù)
argv
:系統(tǒng)或用戶傳入的實(shí)際參數(shù)
1.根據(jù)傳入的第三個(gè)參數(shù),創(chuàng)建UIApplication
對(duì)象
2.根據(jù)傳入的第四個(gè)產(chǎn)生創(chuàng)建UIApplication
對(duì)象的代理
3.設(shè)置剛剛創(chuàng)建出來的代理對(duì)象為UIApplication
的代理
4.開啟一個(gè)事件循環(huán)(可以理解為里面是一個(gè)死循環(huán))這個(gè)時(shí)間循環(huán)是一個(gè)隊(duì)列(先進(jìn)先出)先添加進(jìn)去的先處理
UIApplication生命周期##
1咒程、
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
說明:當(dāng)應(yīng)用程序正常啟動(dòng)時(shí)(不包括已在后臺(tái)轉(zhuǎn)到前臺(tái)的情況)鸠天,調(diào)用此回調(diào)。launchOptions
是啟動(dòng)參數(shù)帐姻,假如用戶通過點(diǎn)擊push通知啟動(dòng)的應(yīng)用稠集,(這是非正常啟動(dòng)的情況,包括本地通知和遠(yuǎn)程通知)饥瓷,這個(gè)參數(shù)里會(huì)存儲(chǔ)一些push通知的信息剥纷。
2、
- (void)applicationWillResignActive:(UIApplication *)application
說明:當(dāng)應(yīng)用程序?qū)⒁敕腔顒?dòng)狀態(tài)執(zhí)行呢铆,在此期間晦鞋,應(yīng)用程序不接收消息或事件,比如來電話了
3棺克、
- (void)applicationDidBecomeActive:(UIApplication *)application
說明:當(dāng)應(yīng)用程序入活動(dòng)狀態(tài)執(zhí)行悠垛,這個(gè)剛好跟上面那個(gè)方法相反
4、
- (void)applicationDidEnterBackground:(UIApplication *)application
說明:當(dāng)程序被推送到后臺(tái)的時(shí)候調(diào)用娜谊。所以要設(shè)置后臺(tái)繼續(xù)運(yùn)行,則在這個(gè)函數(shù)里面設(shè)置即可
5纱皆、
- (void)applicationWillEnterForeground:(UIApplication *)application
說明:當(dāng)程序從后臺(tái)將要重新回到前臺(tái)時(shí)候調(diào)用,這個(gè)剛好跟4相反派草。
6、
- (void)applicationWillTerminate:(UIApplication *)application
說明:當(dāng)程序?qū)⒁顺鍪潜徽{(diào)用近迁,通常是用來保存數(shù)據(jù)和一些退出前的清理工作胡嘿。這個(gè)需要要設(shè)置UIApplicationExitsOnSuspend
的鍵值钳踊。
7勿侯、
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
說明:iPhone設(shè)備只有有限的內(nèi)存拓瞪,如果為應(yīng)用程序分配了太多內(nèi)存操作系統(tǒng)會(huì)終止應(yīng)用程序的運(yùn)行,在終止前會(huì)執(zhí)行這個(gè)方法助琐,通臣拦。可以在這里進(jìn)行內(nèi)存清理工作防止程序被終止
8蛆橡、
- (void)applicationSignificantTimeChange:(UIApplication*)application
說明:當(dāng)系統(tǒng)時(shí)間發(fā)生改變時(shí)執(zhí)行
9、
- (void)applicationDidFinishLaunching:(UIApplication*)application
說明:當(dāng)程序載入后執(zhí)行
10泰演、
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
說明:當(dāng)客戶端注冊(cè)遠(yuǎn)程通知時(shí)睦焕,會(huì)回調(diào)的方法藐握。
如果成功猾普,則回調(diào)這個(gè)方法本谜,客戶端把deviceToken
取出來發(fā)給服務(wù)端,push消息的時(shí)候要用乌助。
如果失敗了眷茁,則回調(diào)下面的方法,可以從error
參數(shù)中看一下失敗原因上祈。
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
11登刺、
- (void)application:(UIApplication)application willChangeStatusBarFrame:(CGRect)newStatusBarFrame
說明:當(dāng)StatusBar框?qū)⒁兓瘯r(shí)執(zhí)行
- (void)application:(UIApplication*)application willChangeStatusBarOrientation:(UIInterfaceOrientation)newStatusBarOrientationduration:(NSTimeInterval)duration
說明:當(dāng)StatusBar框方向?qū)⒁兓瘯r(shí)執(zhí)行
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
說明:當(dāng)StatusBar框方向變化完成后執(zhí)行
- (void)application:(UIApplication*)application didChangeSetStatusBarFrame:(CGRect)oldStatusBarFrame
說明:當(dāng)StatusBar框變化完成后執(zhí)行
12、
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
說明:當(dāng)通過url執(zhí)行
13纸俭、
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
說明:當(dāng)應(yīng)用在前臺(tái)運(yùn)行中,收到遠(yuǎn)程通知時(shí)(不會(huì)彈出系統(tǒng)通知界面)揍很,會(huì)回調(diào)這個(gè)方法窒悔。
當(dāng)應(yīng)用在后臺(tái)狀態(tài)時(shí),點(diǎn)擊push消息啟動(dòng)應(yīng)用简珠,也會(huì)回調(diào)這個(gè)方法。
當(dāng)應(yīng)用完全沒有啟動(dòng)時(shí)膘融,點(diǎn)擊push消息啟動(dòng)應(yīng)用,就不會(huì)回調(diào)這個(gè)方法春畔。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(nonnull NSDictionary *)userInfo fetchCompletionHandler:(nonnull void (^)(UIBackgroundFetchResult))completionHandler
與上一方法相同屯耸,區(qū)別是在后臺(tái)時(shí)亦可執(zhí)行方法疗绣,但要開啟相關(guān)權(quán)限。如圖多矮。
- (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification
說明:當(dāng)應(yīng)用收到本地通知時(shí)會(huì)調(diào)這個(gè)方法塔逃,同上面一個(gè)方法類似。
如果在前臺(tái)運(yùn)行狀態(tài)直接調(diào)用
如果在后臺(tái)狀態(tài)伏蚊,點(diǎn)擊通知啟動(dòng)時(shí)格粪,也會(huì)回調(diào)這個(gè)方法
當(dāng)應(yīng)用完全沒有啟動(dòng)時(shí),點(diǎn)擊push消息啟動(dòng)應(yīng)用比伏,就不會(huì)回調(diào)這個(gè)方法疆导。
[補(bǔ)充]1.iPhone中的應(yīng)用程序很容易受到打擾,比如一個(gè)來電可能導(dǎo)致應(yīng)用程序失去焦點(diǎn)悠菜,如果這個(gè)時(shí)候接聽了電話败富,那么應(yīng)用程序會(huì)轉(zhuǎn)到后臺(tái)運(yùn)行。還有很多其它類似的事件會(huì)導(dǎo)致iPhone應(yīng)用程序失去焦點(diǎn),在應(yīng)用程序失去焦點(diǎn)前會(huì)調(diào)用委托類的applicationWillResignActive()
方法充择,而應(yīng)用程序再次獲取到焦點(diǎn)的時(shí)候會(huì)調(diào)用applicationDidBecomeActive()
方法。比如在運(yùn)行應(yīng)用程序的時(shí)候鎖屏?xí){(diào)用委托類的applicationWillResignActive()
方法宰僧,而當(dāng)屏幕被解鎖的時(shí)候观挎,又會(huì)調(diào)用applicationDidBecomeActive()
方法。
2.另外一個(gè)非常重要的方法就是applicationDidReceiveMemoryWarning()
造成,因?yàn)閕Phone設(shè)備只有有限的內(nèi)存雄嚣,如果為應(yīng)用程序分配了太多內(nèi)存操作系統(tǒng)會(huì)終止應(yīng)用程序的運(yùn)行,但在終止之前操作系統(tǒng)會(huì)通過先調(diào)用委托類的applicationDidReceiveMemoryWarning()
方法警告應(yīng)用程序鼓鲁,在UIApplication
接收到這個(gè)事件后它會(huì)傳遞給委托類的applicationDidReceiveMemoryWarning()
方法港谊,委托類在這個(gè)方法內(nèi)可以進(jìn)行釋放內(nèi)存的操作以防止操作系統(tǒng)強(qiáng)制終止應(yīng)用程序的運(yùn)行。
UIApplication部分常用功能##
1.設(shè)置icon上的數(shù)字圖標(biāo)燥狰,缺省為0
[UIApplication sharedApplication].applicationIconBadgeNumber = 1;
2.設(shè)置搖動(dòng)手勢(shì)的時(shí)候成福,是否支持redo,undo操作,缺省YES
[UIApplication sharedApplication].applicationSupportsShakeToEdit =YES;
3.判斷程序運(yùn)行狀態(tài)
typedef NS_ENUM(NSInteger, UIApplicationState) {
UIApplicationStateActive,
UIApplicationStateInactive,
UIApplicationStateBackground
} NS_ENUM_AVAILABLE_IOS(4_0);
if([UIApplicationsharedApplication].applicationState ==UIApplicationStateInactive){
NSLog(@"程序在運(yùn)行狀態(tài)");
}
4.阻止屏幕變暗進(jìn)入休眠狀態(tài)净当,缺省為no
[UIApplication sharedApplication].idleTimerDisabled =YES;
[注意??]除視頻播放等需要常亮等功能外蕴潦,慎重使用本功能潭苞,因?yàn)?strong>非常耗電。
5.顯示聯(lián)網(wǎng)狀態(tài)動(dòng)畫
[UIApplication sharedApplication].networkActivityIndicatorVisible =YES;
6.設(shè)置狀態(tài)欄的樣式
typedef NS_ENUM(NSInteger, UIStatusBarStyle) {
UIStatusBarStyleDefault = 0, // 默認(rèn)樣式僧诚,黑字,適用于淺色背景(iOS6及以下系統(tǒng)狀態(tài)欄為黑底白字)
UIStatusBarStyleLightContent NS_ENUM_AVAILABLE_IOS(7_0) = 1, // 白字旗扑,適用于深色背景
UIStatusBarStyleBlackTranslucent NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 1,// 白字(iOS6及以下系統(tǒng)在啟動(dòng)界面為灰底白字慈省,iOS7及以上系統(tǒng)與UIStatusBarStyleBlackOpaque效果一樣)
UIStatusBarStyleBlackOpaque NS_ENUM_DEPRECATED_IOS(2_0, 7_0, "Use UIStatusBarStyleLightContent") = 2,// 白字,適用于深色背景(iOS6及以下系統(tǒng)狀態(tài)欄為黑底白字)
} __TVOS_PROHIBITED;
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
隱藏狀態(tài)欄
[UIApplication sharedApplication].statusBarHidden = YES;
7.調(diào)用系統(tǒng)功能
openURL是UIApplication
中一個(gè)非常強(qiáng)大的方法袱衷,使用其可以調(diào)用系統(tǒng)相關(guān)功能笑窜。其方法有
- (BOOL)openURL:(NSURL*)url ;
- (BOOL)canOpenURL:(NSURL *)url ;
[注]在iOS10后新增- (void)openURL:(NSURL*)url options:(NSDictionary<NSString *, id> *)options completionHandler:(void (^ __nullable)(BOOL success))completion
方法
常用方法有:
(1)發(fā)送電子郵件
NSString *recipients =@"mailto:first@example.com?cc=second@example.com,third@example.com&subject=Hello from California!";
NSString *body =@"&body=It is raining in sunny California!";
NSString *email = [NSString stringWithFormat:@"%@%@", recipients, body];
email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:email]];
(2)打電話
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"tel://1234567890"]];
(3)發(fā)送短信
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"sms://466453"]];
(4)打開一個(gè)網(wǎng)址
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"http://itunesconnect.apple.com"]];
[補(bǔ)充] 打開網(wǎng)址的操作通常用于跳轉(zhuǎn)app store怖侦,iOS給好評(píng)時(shí)一般會(huì)直接打開app store應(yīng)用詳情界面,其實(shí)也可以直接跳轉(zhuǎn)到評(píng)論頁(yè)面搬葬,更有利于引導(dǎo)用戶打分和評(píng)論艳悔。(將下面id改成自己的app id即可)
[[UIApplication sharedApplication]openURL:[NSURL URLWithString:@"http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=id1128294199&pageNumber=0&sortOrdering=2&type=Purple+Software&mt=8"]];
直接跳轉(zhuǎn)到詳情
https://itunes.apple.com/cn/app/jia-zhang-mu-ke/id1128294199?mt=8
8.推送相關(guān)
注冊(cè)推送
[[UIApplication sharedApplication]registerUserNotificationSettings:setting];
移除推送
[[UIApplication sharedApplication] cancelAllLocalNotifications];
添加推送
[[UIApplication sharedApplication] scheduleLocalNotification:notification];
更多內(nèi)容會(huì)陸續(xù)補(bǔ)充猜年,歡迎參考指正。
文章參考:
1.UIApplication深入研究-博客園
2.iOS開發(fā)UI篇—程序啟動(dòng)原理-博客園
文章優(yōu)先發(fā)表于:http://keyliu.com
轉(zhuǎn)載請(qǐng)注明出處乔外。