当前位置: 首页 > news >正文

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 里,然后在指定的时间推送指定文字。.


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


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”的授权字符串}
复制代码


权限申请

在使用 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 了。


定制方法如下:

//本地通知
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) {

}];
复制代码

推送小结

整个推送的过程如下


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


比分刷新后为 1:1,在不产生新的推送条目的情况下位置被前置了!


上面简单介绍了 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 和用户的使用情况,了解更多



相关文章:

  • .NET连接MongoDB数据库实例教程
  • rar自动压缩备份
  • Java_BigDecimal类型比较大小
  • 小程序使用smart模板的方法
  • LoadRunner上传文件脚本
  • Android自定义view双缓存技术
  • Linux命令行下运行java.class文件
  • nmap入门之其他
  • 实现IOC功能的简单Spring框架
  • 如何将GridViewEX升级到UWP(Universal Windows Platform)平台
  • Windows环境下安装 mysql-8.0.11-winx64 遇到的问题解决办法
  • LinuxMint下Docker的安装部署和验证
  • Vue-cli / webpack 加载静态js文件的方法
  • python函数的动态传参.作用域与命名空间
  • static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, hello_val_show, hello_val_store); 的作用
  • 【跃迁之路】【699天】程序员高效学习方法论探索系列(实验阶段456-2019.1.19)...
  • Angular 2 DI - IoC DI - 1
  • Angular 响应式表单 基础例子
  • CSS 提示工具(Tooltip)
  • JavaScript 事件——“事件类型”中“HTML5事件”的注意要点
  • JSONP原理
  • PHP 7 修改了什么呢 -- 2
  • SpringCloud集成分布式事务LCN (一)
  • 分享一个自己写的基于canvas的原生js图片爆炸插件
  • 思维导图—你不知道的JavaScript中卷
  • 学习笔记TF060:图像语音结合,看图说话
  • Prometheus VS InfluxDB
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • #{} 和 ${}区别
  • #QT(一种朴素的计算器实现方法)
  • #QT(智能家居界面-界面切换)
  • #在 README.md 中生成项目目录结构
  • %3cli%3e连接html页面,html+canvas实现屏幕截取
  • (8)Linux使用C语言读取proc/stat等cpu使用数据
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (Forward) Music Player: From UI Proposal to Code
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (Python第六天)文件处理
  • (多级缓存)多级缓存
  • (二)hibernate配置管理
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (简单有案例)前端实现主题切换、动态换肤的两种简单方式
  • (四)Tiki-taka算法(TTA)求解无人机三维路径规划研究(MATLAB)
  • *setTimeout实现text输入在用户停顿时才调用事件!*
  • .gitattributes 文件
  • .NET Core 中的路径问题
  • .Net CoreRabbitMQ消息存储可靠机制
  • .Net6使用WebSocket与前端进行通信
  • .net连接MySQL的方法
  • /var/lib/dpkg/lock 锁定问题
  • @AutoConfigurationPackage的使用
  • [ 数据结构 - C++] AVL树原理及实现
  • [20171102]视图v$session中process字段含义
  • [202209]mysql8.0 双主集群搭建 亲测可用
  • [BSGS算法]纯水斐波那契数列