iOS8中 UILocalNotification 和 UIRemoteNotification 使用注意

先说一个关于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当作参数传入了。

相关文章
相关标签/搜索