UNNotifications
是WWDC2016
基于之前的推送服务,推出的全新的的通知框架。
概览
此课程主要分为两大部分。
- 全新的 User Notifictions 框架
- 通知的注册
- 构建通知的内容
- 通知的排期
- 通知的管理
- 通知出发的动作
- 服务的扩展
还有一些更深入的知识,可以等我的下一篇文章。
通知的样式
通知的样式有三种
- 可见的提示框
- 声音和震动
- App图标角标
通知的类型
通知的类型可以分为两类
- 本地通知
- 远程通知
本地通知
本地通知是自身触发的
我们App按照一定规则对系统进行排期,当触发条件达成,就会发出本地通知。
可以触发本地通知的行为有以下三种
- 任务通知
- 日期通知
- 基于定位的通知
远程通知
讲远程通知,首先要知道远程通知的原理。
通过上面这张图,理解起来会比较轻松
我们的iOS
设备和苹果的APNS
服务器一直保持着一个长连接,我们将App注册
通知后,设备与 APNS
服务器通信,由 APNS
服务器返回设备一个Token
,随后这个Token
被上传到我们所需要使用的推送服务器
上。之后当我们需要向设备上推送的时候,我们的推送服务器
直接把要推送的内容
和Token
发送给APNS
,APNS
就可以把信息准确、快速的推送到指定的设备上
APNS
远程通知可以被用于以下场景
- 新闻标题
- 即时通讯
- 信息的实时更新等。。。
远程通知实际上也分为两种
显式的远程通知
显式的远程通知
是设备接到通知之后,会显示在用户的设备界面上,用户可以直观的看
隐式的远程通知
隐式的远程通知
是App在后台时,接收到隐式的远程通知,此时并不会调起程序,而是程序在后台发起请求,更新数据,当用户下一次主动点击,进入App后,直接显示的就是已经更新好数据的页面。
iOS 10 之前通知存在的问题
- 注册繁琐
- 本地通知和远程通知要写不同的代码
- 通知被排期之后管理就变得困难
- 不同平台,通知的区别比较大
User Notifications Framework
基于之前通知平台所存在的问题和不足,WWDC-2016 退出了全新的通知架构 User Notifications Framework
。
通过上图我们可以简要的概括一下这个新框架
- 和之前几乎相同的API。
- 内容扩展(支持标题、子标题、内容以及音视频附件)。
- 本地通知、远程通知的代码可以只写一份。
- 更简单的代理方法。
- 针对通知的管理比以前更加优化(可更新、撤销)。
- 在拓展中对通知进行排期和操作。
- 通知的拓展(可在通知到达设备之前利用 Notification Service 进行操作)!
新的User Notifications Framework
框架可以全平台支持
- 其中
iOS
平台支持全部的新特性 -
WatchOS
平台,可以实现不依靠iOS设备转发
,直接实现本地通知
(例如 实现运动目标、定时通知等)。 -
TV OS
支持角标,可以实现一些特定的提醒通知。
推送流程
推送的流程基本如图所示,下面一一展开来说
1.配置并获取许可(Registration)
// 献上OC版本的代码
-(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
[center requestAuthorizationWithOptions:UNAuthorizationOptionCarPlay |
UNAuthorizationOptionSound |
UNAuthorizationOptionBadge |
UNAuthorizationOptionAlert
completionHandler:^(BOOL granted, NSError * _Nullable error) {
if (granted)
{
NSLog(@" iOS 10 request notification success");
}
else
{
NSLog(@" iOS 10 request notification fail");
}
}];
[[UIApplication sharedApplication] registerForRemoteNotifications];
return YES;
}
iOS 10
可以通过以下方法获取针对通知的用户配置,于是我们可以更加灵活的给用户发出提示
[[UNUserNotificationCenter currentNotificationCenter] getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
NSLog(@"%@",settings);
}];
2.构建推送的内容(Content)
1.针对本地通知
,构建推送内容方式
// OC版本
UNMutableNotificationContent *content = [[UNMutableNotificationContent alloc] init];
content.title = @"Introduction to Notification";
content.subtitle = @"Session 707";
content.body = @"lalalalala";
content.badge = 2;
2.针对远程通知
,构建推送内容方式
3.通知触发(Triggers)
触发一共有四种方式
- 基于
APNS
的推送任务 - 基于
时间间隔
的推送任务 - 基于
日程、日历
的推送任务 - 基于
定位信息
的推送任务
4.排期(Schedule)
本地通知排期
远程通知排期
自此,前端的通知配置完毕
5.代码(code)
import UserNotifications
// 获取用户许可
UNUserNotificationCenter.current().requestAuthorization([.alert, .sound, .badge]) { (granted, error) in ... }
// 构建推送内容
let content = UNMutableNotificationContent()
content.title = "Introduction to Notifications"
content.body = "Let's talk about notifications!"
// 构建触发条件
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
// 构建推送请求
let requestIdentifier = "sampleRequest"
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
// 进行排期
UNUserNotificationCenter.current().add(request) { (error) in // ... } import UserNotifications
Notifiction Handling(前台的通知处理)
为了使我们的程序在前台时依然可以接收通知,我们可以通过实现 UNUserNotificationCenterDelegate
的代理方法,通过这个代理方法,我们可以获取到即将收到的通知
,此时我们就可以在他的Handler回调
中对其进行处理
如果没有传递参数,也就意味着不对其进行处理
Notifiction Management
Notifiction Management
允许开发者访问已经排期等待发出的通知
,甚至可以管理用户已经收到了的通知
。这包括本地通知
和远程通知
。
同时你也可以更新、提升或者删除
已经发送给用户的通知。
其中有个很关键的要素就是请求识别符(RequestIdentifier)
,在本地通知中,它被设置在通知的请求对象上,在远程通知中,在 HTTP/2
有一个新的请求数据头 apns-collapse-id
。
系统通过这个 RequestIdentifier
来得知是哪个通知
我们可以通过官方的示例,来简单的理解这个功能。
- 删除通知
// 比赛开始时给一个标识符
let gameStartIdentifier = "game1.start.identifier"
let gameStartRequest = UNNotificationRequest(identifier: gameStartIdentifier, content: content, trigger: startTrigger)
UNUserNotificationCenter.current().add(gameStartRequest) { (error) in // ... }
// 因为发送了错误的信息,所可以直接取消通知,只要标识符一样即可(比赛结束也可以直接remove掉)
UNUserNotificationCenter.current() .removePendingNotificationRequests(withIdentifiers: [gameStartIdentifier])
- 更新通知
// 比赛开始时给一个标识符
let gameStartIdentifier = "game1.start.identifier"
let gameStartRequest = UNNotificationRequest(identifier: gameStartIdentifier, content: content, trigger: startTrigger)
UNUserNotificationCenter.current().add(gameStartRequest) { (error) in // ... }
// 比赛分数发生改变,需要更新通知,创建一个新的request,但是标识符要一样
let updatedGameStartRequest = UNNotificationRequest(identifier: gameStartIdentifier, content: content, trigger: newStartTrigger)
UNUserNotificationCenter.current().add(updatedGameStartRequest) { (error) in // ... }