先說一個關於UILocalNotification的知識點,容易被忘記:ios
Each app on a device is limited to 64 scheduled local notifications. The system discards scheduled notifications in excess of this limit, keeping only the 64 notifications that will fire the soonest. Recurring notifications are treated as a single notification.app
上面說的是,local notification 最多64個,重複觸發的notification被當成一個。ide
再來一個注意點:ios7 和以上版本函數
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler: (void (^)(UIBackgroundFetchResult))completionHandler 測試
若是這個實現了這個函數,那麼下面這個函數fetch
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfoui
不會被調用!因此只寫上面那個函數就好了。this
在ios8中,有了關於本地通知和遠程通知的新改動,下面來看看。spa
先看一段網上抄來的代碼3d
UIMutableUserNotificationAction *notificationAction1 = [[UIMutableUserNotificationAction alloc] init]; notificationAction1.identifier = @"Accept"; notificationAction1.title = @"Accept"; notificationAction1.activationMode = UIUserNotificationActivationModeBackground; notificationAction1.destructive = NO; notificationAction1.authenticationRequired = NO; UIMutableUserNotificationAction *notificationAction2 = [[UIMutableUserNotificationAction alloc] init]; notificationAction2.identifier = @"Reject"; notificationAction2.title = @"Reject"; notificationAction2.activationMode = UIUserNotificationActivationModeBackground; notificationAction2.destructive = YES; notificationAction2.authenticationRequired = YES; UIMutableUserNotificationAction *notificationAction3 = [[UIMutableUserNotificationAction alloc] init]; notificationAction3.identifier = @"Reply"; notificationAction3.title = @"Reply"; notificationAction3.activationMode = UIUserNotificationActivationModeForeground; notificationAction3.destructive = NO; notificationAction3.authenticationRequired = YES; UIMutableUserNotificationCategory *notificationCategory = [[UIMutableUserNotificationCategory alloc] init]; notificationCategory.identifier = @"Email"; // [notificationCategory setActions:@[notificationAction3] forContext:UIUserNotificationActionContextDefault]; [notificationCategory setActions:@[notificationAction1] forContext:UIUserNotificationActionContextMinimal]; NSSet *categories = [NSSet setWithObjects:notificationCategory, nil]; UIUserNotificationType notificationType = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert; UIUserNotificationSettings *notificationSettings = [UIUserNotificationSettings settingsForTypes:notificationType categories:categories]; [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings]; UILocalNotification* localNotification = [[UILocalNotification alloc] init]; localNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:10]; localNotification.alertBody = @"Testing"; localNotification.category = @"Email"; // Same as category identifier [[UIApplication sharedApplication] scheduleLocalNotification:localNotification];
這是一段發送本地通知的代碼,其中涉及到了此次更新的幾個類,UIMutableUserNotificationAction,UIMutableUserNotificationCategory,UIUserNotificationSettings 咱們須要依次生成這幾個對象,最後使用
[[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];注意,若是註冊了屢次,那麼以最後一次爲準。把程序的通知設定註冊到系統中去。
若是是程序第一次進行註冊,那麼系統會彈出對話框,索取notification權限,對話框內容和notificationSettings的設置無關,都是下圖中的內容
若是點擊不容許,那麼在settings中notification被這是成關閉的,以下圖:
不然,notification就會被打開。
若是UIUserNotificationType notificationType = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert; 那麼settings中的設定項目以下圖:
若是UIUserNotificationType notificationType = UIUserNotificationTypeAlert;那麼settings中的設定項目以下圖:
注意,這個設定中根本不會出現UIUserNotificationTypeBadge | UIUserNotificationTypeSound 相關的設定
有趣的地方來了,若是一開始註冊的設定是
UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert,然後來又註冊了
UIUserNotificationTypeAlert,那麼settings中的圖就會從 左邊的變成右邊的!settings中的設定會根據代碼動態改變!
若是不使用UIUserNotificationTypeAlert,那麼不會彈出notification,對應的提醒內容,能夠在notification center或者鎖屏界面查看。
上面有2個參數UIUserNotificationActionContextDefault 和 UIUserNotificationActionContextMinimal 這裏須要說明一下
官方說明以下
UIUserNotificationActionContextDefault The default context for displaying the alert. In this context, the full UI is displayed for the notification’s alert. You may specify up to four custom actions in this context. UIUserNotificationActionContextMinimal A notification where space is minimal. In this context, a minimal UI is displayed for the notification’s alert. You may specify up to two custom actions in this context.
那麼什麼是Minimal 和default context 呢,見下圖
期中,Banners就是UIUserNotificationActionContextMinimal 而 alerts 就是 UIUserNotificationActionContextDefault!!
若是你使用了UIUserNotificationActionContextDefault,那麼有如下的效果圖
其中的accept,reject,reply是代碼指定的,open是系統提供的,效果如同利用banners樣式時點擊通知內容自己,調用的是didReceiveLocalNotification 或 didReceiveRemoteNotification。
若是代碼中不用UIUserNotificationActionContextMinimal,而在系統設置中用了banners樣式,那麼會使用UIUserNotificationActionContextDefault的多個action中的最後一個,在banners樣式中顯示!
注意,當應用程序在前臺時,通知到來,系統不會爲程序彈出alert(共有3中彈出方式,用戶能夠在settings 中進行設定),而是會調用相應的didReceiveLocalNotification 和 didReceiveRemoteNotification 這2個代理函數,把通知內容交給程序自身處理。而當程序不在前臺時,系統纔會爲用戶彈出alert,提示用戶進行相應操做。
另外,點擊通知中心的通知時,有2中狀況:
一種是程序已經啓動了並且不在前臺,這時,也會調用didReceiveLocalNotification,那麼如何和系統在前臺時調用的didReceiveLocalNotification區別呢?(爲何要區別:通常點擊notification center後進入程序不彈出alert,而程序在前臺時收到通知要彈出alert,這是蘋果程序的通常作法)答案是:能夠經過UIApplication.sharedApplication().applicationState來區別,當從notification center進來,調用didReceiveLocalNotification時 程序的狀態是UIApplicationState.Inactive。
另外一種狀態是程序沒有系統,這時會調用didFinishLaunchingWithOptions函數,把notification經過參數傳入,不會調用
didReceiveLocalNotification 了。
。
這裏UIMutableUserNotificationAction就表明了一個操做,在界面上的表示形式就是一個按鈕,當點擊按鈕時,就會調用
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler
或者 - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler NS_AVAILABLE_IOS(8_0);
不會再調用 didReceiveLocalNotification 或 didReceiveRemoteNotification 這2個代理函數了。
另外,在UIMutableUserNotificationAction 中有一個屬性,activationMode,當它是UIUserNotificationActivationModeBackground時,系統會選在在後臺調用handleActionWithIdentifier函數,並執行裏面的代碼,不啓動程序界面。
,執行的時間是有限的,我測試的是30s,若是超過30s你的程序還在後臺執行,那麼系統會終止調你的程序,並拋出異常。異常以下
<Warning>: <BKNewProcess: 0x17e685f0; -.bbbb; pid: 922; hostpid: -1> has active assertions beyond permitted time: {( <BKProcessAssertion: 0x17d6b4f0> id: 42-2B9D290F-7F21-4DCB-955B-9D80DE693382 name: Notification action process: <BKNewProcess: 0x17e685f0; -.bbbb; pid: 922; hostpid: -1> permittedBackgroundDuration: 30.000000 reason: notificationAction owner pid:42 preventSuspend preventThrottleDownUI preventIdleSleep preventSuspendOnSleep , <BKProcessAssertion: 0x17d6de50> id: 42-707C3B54-51BC-47DA-B779-B11888416FE4 name: Deliver Message process: <BKNewProcess: 0x17e685f0; -.bbbb; pid: 922; hostpid: -1> permittedBackgroundDuration: 10.000000 reason: suspend owner pid:42 preventSuspend preventThrottleDownCPU preventThrottleDownUI preventSuspendOnSleep )}
注意,雖然你設置了action,可是若是你沒有點擊action按鈕,而是經過點擊通知內容自己出發消息,那麼系統扔會像ios7同樣,調用didReceiveLocalNotification 或 didReceiveRemoteNotification 這2個代理函數(能夠本身體驗一下ios8通知的操做方法))。
若是程序沒有啓動,用戶點擊action按鈕後,系統會先調用didFinishLaunchingWithOptions啓動程序,再調用
- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forLocalNotification:(UILocalNotification *)notification completionHandler:(void (^)())completionHandler 或者 - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler NS_AVAILABLE_IOS(8_0);
來處理action,這一點和之前點擊通知內容自己的效果不同,點擊內容自己時,是不會調用didReceiveLocalNotification函數的,僅僅調用didFinishLaunchingWithOptions。我感受這是由於action處理比較複雜,沒法再直接附加在didFinishLaunchingWithOptions當作參數傳入了。