iOS 10 的推送 User Notifications Framework

介绍

User Notifications Framework 是苹果在 WWDC 2016 推出的。iOS 10 中以前杂乱的和通知相关的 API 都被统一了,现在开发者可以使用独立的 UserNotifications.framework 来集中管理和使用 iOS 系统中通知的功能。在此基础上,Apple 还增加了撤回单条通知,更新已展示通知,中途修改通知内容,在通知中展示图片视频,自定义通知 UI 等一系列新功能,非常强大。

iOS 10 以前的推送

iOS 10 以前推送分为 Local Notifications(本地推送) 和 Remote Notifications(远程推送)。

本地推送:通过 App 本地定制,加入到系统的 Schedule 里,然后在指定的时间推送指定文字。
iOS 10 的推送 User Notifications Framework

远程推送:通过服务端向苹果推送服务器 Apple Push Notification Service (APNs) 发送 Notification Payload,之后 APNs 再将推送下发到指定设备的 指定 App 上。
iOS 10 的推送 User Notifications Framework
User Notifications Framework

基本配置

如果只是简单的本地推送,跳过 1 、2 步骤,直接到步骤 3。

1、 如果你的 App 有远端推送的话,那你需要开发者账号的,需要新建一个对应你 bundle 的 push 证书。 具体的证书制作请参考这里
2、 Capabilities 中打开 Push Notifications 开关在 XCode7 中这里的开关不打开,推送也是可以正常使用的,但是在 XCode8 中,这里的开关必须要打开,不然会报错:

Error Domain=NSCocoaErrorDomain Code=3000 "未找到应用程序的“aps-environment”的授权字符串" UserInfo={NSLocalizedDescription=未找到应用程序的“aps-environment”的授权字符串}

iOS 10 的推送 User Notifications Framework

权限申请

在使用 UserNotifications 框架的 API 的时候,首先要导入 UserNotifications 框架:

#import <UserNotifications/UserNotifications.h>

注册推送

UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
    if (!error)
        {
            NSLog(@"请求授权成功");
        }
        else
        {
            NSLog(@"请求授权失败");
        }
}];

Notification settings:之前注册推送服务,用户点击了同意还是不同意,以及用户之后又做了怎样的更改我们都无从得知,现在 apple 开放了这个 API,我们可以直接获取到用户的设定信息了。注意 UNNotificationSettings 是只读对象哦,不能直接修改!只能通过以下方式获取

[center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
    NSLog(@"%@", settings);
}];

打印

<UNNotificationSettings: 0x6000022f9dc0; 
authorizationStatus: NotDetermined, 
notificationCenterSetting: NotSupported, 
soundSetting: NotSupported, 
badgeSetting: NotSupported, 
lockScreenSetting: NotSupported, 
carPlaySetting: NotSupported, 
criticalAlertSetting: NotSupported, 
alertSetting: NotSupported, 
alertStyle: None, 
providesAppNotificationSettings: No>

Token Registration

[[UIApplication sharedApplication] registerForRemoteNotifications];

获取设备的Device Token

/获取DeviceToken成功
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
    NSString *deviceString = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    deviceString = [deviceString stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSLog(@"deviceToken:%@",deviceString);
}

//获取DeviceToken失败
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
{
    NSLog(@"[DeviceToken Error]:%@\n",error.description);
}

接收推送的代理方法

// App处于前台接收通知时
// 只有app处于前台状态下才会调用,后台状态或者应用杀死下是不会调用这个方法的
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler 

// App通知的点击事件
// 用户点击消息才会触发
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler 

苹果把本地通知跟远程通知合二为一。区分本地通知跟远程通知的类是UNPushNotificationTrigger.h 类中,UNPushNotificationTrigger 的类型是新增加的。

UNPushNotificationTrigger (远程通知) 远程推送的通知类型
UNTimeIntervalNotificationTrigger (本地通知) 一定时间之后,重复或者不重复推送通知。我们可以设置timeInterval(时间间隔)和repeats(是否重复)。
UNCalendarNotificationTrigger(本地通知) 一定日期之后,重复或者不重复推送通知 例如,你每天8点推送一个通知,只要dateComponents为8,如果你想每天8点都推送这个通知,只要repeats为YES就可以了。
UNLocationNotificationTrigger (本地通知)地理位置的一种通知,
当用户进入或离开一个地理区域来通知。

内容

以前只能展示一条文字,现在可以有 title 、subtitle 以及 body 了。
iOS 10 的推送 User Notifications Framework
定制方法如下:

//本地通知
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = @"CALENDAR";
content.subtitle = @"Lunch";
content.body = @"Today at 12:00 PM";
content.badge = @1;

//远程推送
{
"aps" : {
    "alert" : { 
         "title" : "CALENDAR", 
         "subtitle" : "Lunch",         
         "body" : "Today at 12:00 PM"
                },
    "badge" : 1
        },
}

Triggers

UNTimeIntervalNotificationTrigger 定时推送
UNCalendarNotificationTrigger 定期推送
UNLocationNotificationTrigger 定点推送

//60 秒后提醒
//timeInterval:单位为秒(s)  repeats:是否循环提醒
UNTimeIntervalNotificationTrigger *trigger1 = [UNTimeIntervalNotificationTrigger triggerWithTimeInterval:60 repeats:NO];

// 在每周一早上 8:00 提醒
NSDateComponents *components = [[NSDateComponents alloc] init];
components.weekday = 2;
components.hour = 8;
UNCalendarNotificationTrigger *trigger3 = [UNCalendarNotificationTrigger triggerWithDateMatchingComponents:components repeats:YES];

//首先得导入#import <CoreLocation/CoreLocation.h>,不然会regin创建有问题。
CLLocationCoordinate2D center1 = CLLocationCoordinate2DMake(31.234567, 117.4567890);
  CLCircularRegion *region = [[CLCircularRegion alloc] initWithCenter:center1 radius:500 identifier:@"桂林路"];
UNLocationNotificationTrigger *trigger4 = [UNLocationNotificationTrigger triggerWithRegion:region repeats:NO];

Add Request

NSString *requestIdentifier = @"sampleRequest";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier
                                                                          content:content
                                                                          trigger:trigger1];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {

}];

推送小结

整个推送的过程如下
iOS 10 的推送 User Notifications Framework
Local Notifications 通过定义 Content 和 Trigger 向 UNUserNotificationCenter 进行 request 这三部曲来实现。
Remote Notifications 则向 APNs 发送 Notification Payload 。

Notification Handling

设定了推送,然后就结束了?iOS 10 并没有这么简单!
通过实现协议,使 App 处于前台时捕捉并处理即将触发的推送:

@interface AppDelegate () <UNUserNotificationCenterDelegate>

- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
{
    completionHandler(UNNotificationPresentationOptionAlert | UNNotificationPresentationOptionSound);
}

让它只显示 alert 和 sound ,而忽略 badge 。

Notification Management

彻底掌控整个推送周期:

Local Notification 通过更新 request
Remote Notification 通过新的字段 apns-collapse-id

通过之前的 addNotificationRequest: 方法,在 id 不变的情况下重新添加,就可以刷新原有的推送。

NSString *requestIdentifier = @"sampleRequest";
UNNotificationRequest *request = [UNNotificationRequest requestWithIdentifier:requestIdentifier
                                                                      content:newContent
                                                                      trigger:newTrigger1];
[center addNotificationRequest:request withCompletionHandler:^(NSError * _Nullable error) {

}];

删除计划的推送:

[center removePendingNotificationRequestsWithIdentifiers:@[requestIdentifier]];

此外 UNUserNotificationCenter.h 中还有诸如删除所有推送、查看已经发出的推送、删除已经发出的推送等等强大的接口。

刷新原有的推送后,在通知中心的显示里,也会有相应的变化,这里注意第 2 条信息,现在比分是 1:0

iOS 10 的推送 User Notifications Framework
比分刷新后为 1:1,在不产生新的推送条目的情况下位置被前置了!
iOS 10 的推送 User Notifications Framework
上面简单介绍了 iOS 10 的新框架 User Notifications Framework,了解完 iOS 10 的框架之后,还要适配iOS 8 9 系统,是不是觉得很麻烦,笔者最近发现了一款 SDK ---- MobPush,兼容 iOS 8-12 系统,接入非常简单,3行代码就可以搞定推送。

MPushNotificationConfiguration *configuration = [[MPushNotificationConfiguration alloc] init];
configuration.types = MPushAuthorizationOptionsBadge | MPushAuthorizationOptionsSound | MPushAuthorizationOptionsAlert;
[MobPush setupNotification:configuration];

同时,MobPush 支持多样化推送场景、用户分群、AB 测试、智能推送等等功能,还有完善的数据统计后台可以从多个维度实时了解 APP 和用户的使用情况

上一篇:[云原生]Kubernetes - 集群搭建(第2章)


下一篇:K8S启动失败,kubelet.service: main process exited, code=exited, status=1/FAILURE