一:首先查看一下關於UIApplication的定義 UIApplication的核心作用是提供了iOS程式運行期間的控制和協作工作。它的基類是UIResponder;每一個程式在運行期必須有且僅有一個UIApplication(或則其子類)的一個實例;在程式開始運行的時候,UIApplicatio ...
一:首先查看一下關於UIApplication的定義
NS_CLASS_AVAILABLE_IOS(2_0) @interface UIApplication : UIResponder //獲得單例對象 + (UIApplication *)sharedApplication NS_EXTENSION_UNAVAILABLE_IOS("Use view controller based solutions where appropriate instead."); //委托 @property(nullable, nonatomic,assign) id<UIApplicationDelegate> delegate; //暫停觸摸事件 - (void)beginIgnoringInteractionEvents NS_EXTENSION_UNAVAILABLE_IOS(""); // 告訴接受者繼續處理 touch相關的事件 - (void)endIgnoringInteractionEvents NS_EXTENSION_UNAVAILABLE_IOS(""); // 是否忽略交互事件 - (BOOL)isIgnoringInteractionEvents; //阻止屏幕變暗進入休眠狀態 ,耗電,慎重預設NO @property(nonatomic,getter=isIdleTimerDisabled) BOOL idleTimerDisabled; // 通過特定的URL中打開資源 - (BOOL)openURL:(NSURL*)url NS_EXTENSION_UNAVAILABLE_IOS(""); // 返回一個bool值, 是否從已經安裝的 apps 中跳轉 - (BOOL)canOpenURL:(NSURL *)url NS_AVAILABLE_IOS(3_0); // 發送事件給app內適用的響應者 - (void)sendEvent:(UIEvent *)event; // app的主 window 只讀 @property(nullable, nonatomic,readonly) UIWindow *keyWindow; // 隱藏的和看得見的所有 window @property(nonatomic,readonly) NSArray<__kindof UIWindow *> *windows; // 發送一個含選擇器的動作消息到指定的目標 - (BOOL)sendAction:(SEL)action to:(nullable id)target from:(nullable id)sender forEvent:(nullable UIEvent *)event; // 是否顯示網路正在活動,預設是NO @property(nonatomic,getter=isNetworkActivityIndicatorVisible) BOOL networkActivityIndicatorVisible; //狀態欄樣式 @property(readonly, nonatomic) UIStatusBarStyle statusBarStyle; // default is UIStatusBarStyleDefault //狀態欄隱藏 @property(readonly, nonatomic,getter=isStatusBarHidden) BOOL statusBarHidden; //屏幕旋轉方向 @property(readonly, nonatomic) UIInterfaceOrientation statusBarOrientation; // 在指定的視窗中, 返回預設的視圖控制器方向介面 - (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window NS_AVAILABLE_IOS(6_0); // 狀態欄動畫持續時間 @property(nonatomic,readonly) NSTimeInterval statusBarOrientationAnimationDuration; // 獲取狀態欄的 rect @property(nonatomic,readonly) CGRect statusBarFrame; // 未讀消息數字,0表示隱藏 @property(nonatomic) NSInteger applicationIconBadgeNumber; // 是否接受搖晃的時候, 展現 撤銷和恢復 視圖 @property(nonatomic) BOOL applicationSupportsShakeToEdit NS_AVAILABLE_IOS(3_0); // app當前的運行的狀態 @property(nonatomic,readonly) UIApplicationState applicationState NS_AVAILABLE_IOS(4_0); // app 在後臺運行的時間 @property(nonatomic,readonly) NSTimeInterval backgroundTimeRemaining NS_AVAILABLE_IOS(4_0); //標記開始新的長時間運行的後臺任務 - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithExpirationHandler:(void(^ __nullable)(void))handler NS_AVAILABLE_IOS(4_0) NS_REQUIRES_SUPER; // 標記新的長時間運行的任務以及指定任務的命名 - (UIBackgroundTaskIdentifier)beginBackgroundTaskWithName:(nullable NSString *)taskName expirationHandler:(void(^ __nullable)(void))handler NS_AVAILABLE_IOS(7_0) NS_REQUIRES_SUPER; // 結束指定的長時間的後臺任務 - (void)endBackgroundTask:(UIBackgroundTaskIdentifier)identifier NS_AVAILABLE_IOS(4_0) NS_REQUIRES_SUPER; // 指定最小時間間隔在後臺獲取操作 - (void)setMinimumBackgroundFetchInterval:(NSTimeInterval)minimumBackgroundFetchInterval NS_AVAILABLE_IOS(7_0); //進入到後臺,是否能夠進行後臺的操作 @property (nonatomic, readonly) UIBackgroundRefreshStatus backgroundRefreshStatus NS_AVAILABLE_IOS(7_0); @property(nonatomic,readonly,getter=isProtectedDataAvailable) BOOL protectedDataAvailable NS_AVAILABLE_IOS(4_0); // 返回用戶界面的佈局方向。只讀 @property(nonatomic,readonly) UIUserInterfaceLayoutDirection userInterfaceLayoutDirection NS_AVAILABLE_IOS(5_0); // 字體偏好 只讀 @property(nonatomic,readonly) NSString *preferredContentSizeCategory NS_AVAILABLE_IOS(7_0); @end
UIApplication的核心作用是提供了iOS程式運行期間的控制和協作工作。它的基類是UIResponder;每一個程式在運行期必須有且僅有一個UIApplication(或則其子類)的一個實例;在程式開始運行的時候,UIApplicationMain函數是程式進入點,這個函數做了很多工作,其中一個重要的工作就是創建一個UIApplication的單例實例。在你的代碼中你,你可以通過調用[UIApplication sharedApplication]來得到這個單例實例的指針。UIApplication的一個主要工作是處理用戶事件,它會維護一個隊列,把所有用戶事件都放入隊列,逐個處理,在處理的時候,它會發送當前事件到一個合適的處理事件的目標控制項。此外,UIApplication實例還維護一個在本應用中打開的window列表(UIWindow實例),這樣它就可以接觸應用中的任何一個UIView對象。UIApplication實例會被賦予一個代理對象,以處理應用程式的生命周期事件(比如程式啟動和關閉)、系統事件(比如來電、記事項警告)等等。
知識點1:屬性的運用
//通過sharedApplication獲取該程式的UIApplication對象 UIApplication *app=[UIApplication sharedApplication]; app.applicationIconBadgeNumber=100;
知識點2:關於openURL的運用
/* NSURL統一資源定位符 格式 > 協議://路徑 */ // 創建UIApplication對象 UIApplication *app = [UIApplication sharedApplication]; // 打電話 tel為打電話協議 [app openURL:[NSURL URLWithString:@"tel://10086"]]; // 發簡訊 sms為發簡訊協議 [app openURL:[NSURL URLWithString:@"sms://10086"]]; // 打開網址 http為上網協議 [app openURL:[NSURL URLWithString:@"http://www.ithemima.com"]]; // 發送郵件 mailto為發送郵件協議 [app openURL:[NSURL URLWithString:@"mailto://[email protected]"]];
知識點3:狀態欄的管理從iOS7開始,系統提供了2種管理狀態欄的方式
a: 通過UIViewController管理(每一個UIViewController都可以擁有自己不同的狀態欄)
b: 通過UIApplication管理(一個應用程式的狀態欄都由它統一管理)
在iOS7之後,預設情況下,狀態欄都是由UIViewController管理的,若想通過UIApplication進行管理,則需要配置plist文件:View controller-based status bar appearance 設置成NO (預設值為YES)
// 示範代碼: // 隱藏系統狀態欄 [UIApplication sharedApplication].statusBarHidden = YES; // 設置系統狀態欄樣式 [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; // 隱藏系統狀態欄帶動畫 [[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide]; // 設置系統狀態欄樣式帶動畫 [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:YES];
二:UIApplication (UIRemoteNotifications)分類,處理遠程通知
@interface UIApplication (UIRemoteNotifications) //在iOS8中,我們使用新的函數來註冊通知 - (void)registerForRemoteNotifications NS_AVAILABLE_IOS(8_0); //關閉推送 - (void)unregisterForRemoteNotifications NS_AVAILABLE_IOS(3_0); //獲取本地推送授權狀態 - (BOOL)isRegisteredForRemoteNotifications NS_AVAILABLE_IOS(8_0); //授權狀態的枚舉類型 //UIUserNotificationTypeNone 無授權 //UIUserNotificationTypeBadge 更新APP圖標角標 //UIUserNotificationTypeSound 播放聲音 //UIUserNotificationTypeAlert 屏幕中間彈出一個UIAlertView - (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types NS_DEPRECATED_IOS(3_0, 8_0, "Please use registerForRemoteNotifications and registerUserNotificationSettings: instead"); //獲取通知中心 是否 允許程式通知消息的值。 - (UIRemoteNotificationType)enabledRemoteNotificationTypes NS_DEPRECATED_IOS(3_0, 8_0, "Please use -[UIApplication isRegisteredForRemoteNotifications], or -[UIApplication currentUserNotificationSettings] to retrieve user-enabled remote notification and user notification settings"); @end
知識點1:授權的方法實例
UIUserNotificationType type = UIUserNotificationTypeBadge | UIUserNotificationTypeAlert | UIUserNotificationTypeSound; UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:type categories:nil]; [[UIApplication sharedApplication] registerUserNotificationSettings:setting];
知識點2:遠程推送通知實現的條件
所有的蘋果設備,在聯網狀態下,都會和蘋果伺服器APNs建立一個長連接;遠程推送通知就是藉助蘋果設備與APNs伺服器之間的長連接,藉助APNs伺服器講消息發送給客戶端。遠程推送通知實現的條件,必須有真機,只有真機具備UDID,才能生成deviceToken設備令牌(deviceToken的生成演算法只有Apple掌握,為了確保演算法發生變化後仍然能夠正常接收伺服器端發送的通知,每次應用程式啟動都重新獲得deviceToken);需要開發推送Cer證書;
知識點3:遠程推送通知步驟:
1:iOS8以後,使用遠程通知,需要請求用戶授權 2:註冊遠程通知成功後會調用以下方法,獲取deviceToken設備令牌: -(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken; 3:把deviceToken設備令牌發送給伺服器,時刻保持deviceToken是最新的 4:監聽遠程推送通知: -(void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo;
知識點4:判斷是否打開推送 IOS7跟IOS8也是有區別
if ([[UIDevice currentDevice].systemVersion floatValue]>=8.0f) { UIUserNotificationSettings *setting = [[UIApplication sharedApplication] currentUserNotificationSettings]; if (UIUserNotificationTypeNone == setting.types) { NSLog(@"推送關閉 8.0"); } else { NSLog(@"推送打開 8.0"); } } else { UIRemoteNotificationType type = [[UIApplication sharedApplication] enabledRemoteNotificationTypes]; if(UIRemoteNotificationTypeNone == type){ NSLog(@"推送關閉"); } else { NSLog(@"推送打開"); } }
知識點5:IOS7跟IOS8關於註冊通知是有差異
@interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. //首次打開應用,跳轉登錄界面 //登錄成功,跳轉主界面 [self LoadMainView]; //註冊遠程通知 if ([[UIDevice currentDevice].systemVersion floatValue] < 8.0) { UIRemoteNotificationType type = UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound; [application registerForRemoteNotificationTypes:type]; } else { UIUserNotificationType type = UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound; UIUserNotificationSettings *setting = [UIUserNotificationSettings settingsForTypes:type categories:nil]; [application registerUserNotificationSettings:setting]; } return YES; } #pragma mark 註冊遠程通知代理方法,返回deviceToken #ifdef __IPHONE_8_0 - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { //iOS8之後註冊遠程通知需要實現代理方法: [application registerForRemoteNotifications]; } - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler { //handle the actions if ([identifier isEqualToString:@"declineAction"]){ } else if ([identifier isEqualToString:@"answerAction"]){ } } #endif - (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSString* newToken = [[[NSString stringWithFormat:@"%@",deviceToken] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]] stringByReplacingOccurrencesOfString:@" " withString:@""]; NSLog(@"nsdata:%@\n 字元串token: %@",deviceToken, newToken);// 獲取device token //將token發送給伺服器 } - (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { NSLog(@"RegistFail %@",error); } - (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { //接收通知內容 }
三:UIApplication (UILocalNotifications)分類 處理本地通知
@interface UIApplication (UILocalNotifications) //立刻推送,忽略本地通知對象的fireDate設置進行本地推送通知 - (void)presentLocalNotificationNow:(UILocalNotification *)notification NS_AVAILABLE_IOS(4_0); //延時推送,根據本地通知對象的fireDate設置進行本地推送通知 - (void)scheduleLocalNotification:(UILocalNotification *)notification NS_AVAILABLE_IOS(4_0); //取消指定的本地推送通知 - (void)cancelLocalNotification:(UILocalNotification *)notification NS_AVAILABLE_IOS(4_0); //取消全部本地推送通知 - (void)cancelAllLocalNotifications NS_AVAILABLE_IOS(4_0); //獲取本地推送數組 @property(nullable,nonatomic,copy) NSArray<UILocalNotification *> *scheduledLocalNotifications NS_AVAILABLE_IOS(4_0); @end
知識點1:推送通知分為
本地推送通知:
不需要聯網,在APP代碼中推送的通知,確定知道未來某個時間點應該提醒用戶什麼【開發人員在APP內部通過代碼發生 = 本地推送通知】
遠程推送通知:
需要聯網,是由伺服器推送的通知,不確定未來某個時間點應該提醒用戶什麼【伺服器可以確定通知時間和內容 = 遠程推送通知】
知識點2:本地推送通知步驟
1:在iOS8以後使用本地推送通知,需要得到用戶的許可 2:創建UILocalNotification本地通知對象,並設置必要屬性 3:開始本地推送通知: 第一種方法,延時推送,根據本地通知對象的fireDate設置進行本地推送通知 [[UIApplication shareApplication] scheduleLocalNotification:notification]; 第二種方法,立刻推送,忽略本地通知對象的fireDate設置進行本地推送通知 [[UIApplication shareApplication] presentLocalNotificationNow:notification]; 4:監聽用戶點擊通知: APP處於前臺,此時不會彈框通知用戶,但會調用對應的代理方法 : -(void)application:(UIApplication *)application didReceiveLocalNotification; APP處於後臺,屏幕上方會彈出橫幅,用戶點擊橫幅後,會進入前臺,調用上面的代理方法。 APP已關閉,屏幕上方會彈出橫幅,用戶點擊橫幅後,會啟動APP,調用以下方法: -(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; /* 通過參數launchOptions獲取本地推送通知內容 */ UILocalNotification *local = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; 5:調用UIApplication的對象方法,取消本地推送通知: /* 取消指定的本地推送通知 */ -(void)cancelLocalNotification:(UILocalNotification *)notification; /* 取消全部本地推送通知 */ -(void)cancelAllLocalNotification;
知識點3:實例代碼
1. 註冊通知代碼以及UIAlertView顯示通知方法代碼
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //因為是storyboard啟動,這裡就沒有其他啟動代碼了 //iOS8.0以後,如果需要使用推送通知,需要得到用戶許可 if (application.currentUserNotificationSettings.types == UIUserNotificationTypeNone) { //註冊通知,有橫幅通知、應用數字通知、應用聲音通知 UIUserNotificationSettings * setting = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil]; [application registerUserNotificationSettings:setting]; } else { //當APP關閉後接收到通知,在啟動中獲取本地推送通知對象 UILocalNotification *notification = launchOptions[UIApplicationLaunchOptionsLocalNotificationKey]; [self showLocalNotification:notification]; } return YES; } /* 彈框UIAlertView顯示本地通知的信息 */ - (void)showLocalNotification:(UILocalNotification *)notification { /* 顯示本地通知 */ NSDictionary *userInfo = notification.userInfo; NSString *title = @"本地通知"; NSString *msg = userInfo[@"msg"]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:msg delegate:nil cancelButtonTitle:@"取消" otherButtonTitles:@"確定", nil]; [alert show]; //移除本地通知 [[UIApplication sharedApplication] cancelLocalNotification:notification]; }
2. 創建本地通知代碼
/* 創建一個本地通知 */ - (UILocalNotification *)makeLocalNotification{ //創建本地推送通知對象 UILocalNotification *notification = [[UILocalNotification alloc] init]; //設置調用時間 notification.fireDate = [NSDate dateWithTimeIntervalSinceNow:10.0];//通知觸發的時間,10s以後 notification.repeatInterval = NSCalendarUnitMinute;//每隔多久重覆發一次本地通知 //設置通知屬性 notification.alertBody = @"最近添加了諸多有趣的特性,是否立即體驗?";//通知主體 notification.applicationIconBadgeNumber = 1;//應用程式圖標右上角顯示的消息數 notification.alertAction = @"打開應用"; //待機界面的滑動動作提示 notification.alertLaunchImage = @"Default";//通過點擊通知打開應用時的啟動圖片,這裡使用程式啟動圖片 notification.soundName = UILocalNotificationDefaultSoundName;//收到通知時播放的聲音,預設消息聲音 //設置用戶信息 notification.userInfo = @{ @"id":@1, @"user":@"Kenshin Cui", @"msg":@"我來了一發本地通知"};//綁定到通知上的其他附加信息 return notification; }
如果需要每天的中午12點準時本地推送怎麼辦呢?就像這麼辦,修改fireDate和repeatInterval屬性
NSDateFormatter *formatter1 = [[NSDateFormatter alloc]init]; [formatter setDateFormat:@"yyyy-MM-dd HH-mm-sss"]; NSDate *resDate = [formatter dateFromString:@"2016-04-09 12-00-00"]; notification.fireDate = resDate;//設定為明天中午12點觸發通知 //記得設置當前時區,沒有設置的話,fireDate將不考慮時區,這樣的通知會不准確 notification.timeZone = [NSTimeZone defaultTimeZone]; notification.repeatInterval = NSCalendarUnitDay;//每隔一天觸發一次
3:監聽用戶點擊
/* 註冊本地通知完成會調用,即用戶點擊確定授權後調用 */ - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { //在這裡我們嘗試發送本地推送通知 if (notificationSettings.types != UIUserNotificationTypeNone) { UILocalNotification *notification = [self makeLocalNotification]; //延遲調用通知 [application scheduleLocalNotification:notification]; //立刻發送通知 //[application presentLocalNotificationNow:notification]; } } /* 應用還在運行,無論前臺還是後臺,都會調用該方法處理通知 */ - (void)application:(UIApplication *)application didReceiveLocalNotification:(UILocalNotification *)notification { if( notification ) { [self showLocalNotification:notification]; } } /* 應用進入前臺,去除應用邊角數字顯示 */ - (void)applicationWillEnterForeground:(UIApplication *)application { //去除應用邊角數字 [application setApplicationIconBadgeNumber:0]; }
四:UIApplication (UIUserNotificationSettings)分類 ios8遠程通知註冊
@class UIUserNotificationSettings; @interface UIApplication (UIUserNotificationSettings) // IOS8註冊遠程通知 - (void)registerUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings NS_AVAILABLE_IOS(8_0); // IOS8獲得當前的通知設置 - (nullable UIUserNotificationSettings *)currentUserNotificationSettings NS_AVAILABLE_IOS(8_0); @end
五:UIApplication (UIRemoteControlEvents)分類 遠程事件開關
@interface UIApplication (UIRemoteControlEvents) //允許傳遞遠程式控制制事件 - (void)beginReceivingRemoteControlEvents NS_AVAILABLE_IOS(4_0); //關閉遠程式控制制 - (void)endReceivingRemoteControlEvents NS_AVAILABLE_IOS(4_0); @end
結合遠程事件的運用;接收到一個遠程式控制制事件。比如耳機控制。允許傳遞遠程式控制制事件,必須調用UIApplication的beginReceivingRemoteControlEvents方法;關閉遠程式控制制,調用endReceivingRemoteControlEvents。
六:UIApplication (UIStateRestoration)分類 控制狀態恢復
@protocol UIStateRestoring; @interface UIApplication (UIStateRestoration) // 非同步恢復狀態 - (void)extendStateRestoration NS_AVAILABLE_IOS(6_0); // 結束非同步恢復狀態 - (void)completeStateRestoration NS_AVAILABLE_IOS(6_0); // 阻止應用程式使用最近的快找圖像,在接下來的迴圈中 - (void)ignoreSnapshotOnNextApplicationLaunch NS_AVAILABLE_IOS(7_0); // 註冊自定義對象的使用狀態恢復系統 + (void)registerObjectForStateRestoration:(id<UIStateRestoring>)object restorationIdentifier:(NSString *)restorationIdentifier NS_AVAILABLE_IOS(7_0); @end
七:UIApplicationDelegate協議
//主要方法有: //應用程式的生命周期 //應用程式啟動完成的時候調用 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSLog(@"%s",__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)applicationWillTerminate:(UIApplication *)application { NSLog(@"%s",__func__); }