iOS10新增加了一个UserNotificationKit(用户通知框架)来整合通知相关的API,UserNotificationKit框架增加了很多令人惊喜的特性:

  • 更加丰富的推送内容:现在可以设置推送的title、subtitle、body 以及符合大小的图片、音频、视频等附件内容。
  • 更好的通知管理:现在可以对通知进行查看、更新、删除了。
  • 更优雅的展示方式:可以设置应用在前台展示通知。

对iOS10而言,UserNotificationKit(用户通知框架)是一种系统层面的UI展示,远程通知APNS只是通知的一种触发方式,UserNotificationKit的重要意义在于统一了Remote(远程通知)和Local(本地通知)。

UserNotificationKit 基本流程

UserNotificationKit使用大概分为以下几个过程:

  • 注册通知: 获取相关权限,注册APNS
  • 发送通知: 创建通知并发起通知请求
  • 处理通知: 处理通知回调,对通知进行额外的操作

首先你需要向用户请求通知权限,在取得权限后注册通知;
然后你可以创建一个通知并发起推送,当然对于远程推送APNS而言,你还需要注册DeviceToken;
在接受到推送通知后可以根据app的运行情况决定是否展示通知,当然你也可以通过一系列的回调接口对通知进行处理加工。

注册通知

请求权限

iOS 10 进一步消除了本地推送和远程推送的区别,因为两者在申请权限的时候都是在打断用户的行为。因此iOS 10统一了推送权限的申请:

//iOS8以下
[application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
//iOS8 - iOS10
[application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil]];
//iOS10
UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
UNAuthorizationOptions options = UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert;
[center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError * _Nullable error) { }
//iOS10 swift
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]{ granted, error in
}

推送设置

iOS 10 还可以实时获取用户当前的推送的设置:

//可以获取的设置参数
@available(iOS 10.0, *)
open class UNNotificationSettings : NSObject, NSCopying, NSSecureCoding {
open var authorizationStatus: UNAuthorizationStatus { get }
open var soundSetting: UNNotificationSetting { get }
open var badgeSetting: UNNotificationSetting { get }
open var alertSetting: UNNotificationSetting { get }
open var notificationCenterSetting: UNNotificationSetting { get }
open var lockScreenSetting: UNNotificationSetting { get }
open var carPlaySetting: UNNotificationSetting { get }
open var alertStyle: UNAlertStyle { get }
}
//获取设置
UNUserNotificationCenter.current().getNotificationSettings {
settings in
print(settings.authorizationStatus) // .authorized | .denied | .notDetermined
print(settings.badgeSetting) // .enabled | .disabled | .notSupported
}

在有些情况下,可以对推送权限设置进行检查。

APNS:DeviceToken

一旦获得用户权限后,你就可以在应用中发送本地通知了。不过对于APNS而言,你还需要申请DeviceToken,把DeviceToken传递给服务器,然后服务器根据DeviceToken发送到对应的用户。

//向APNSS请求deviceToken:
UIApplication.shared.registerForRemoteNotifications()
//回调
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
print("Get Push token: \(deviceToken)")
}

发送通知

本地通知发送的基本流程

1.设置推送内容
2.设置通知触发器
3.添加通知

1.设置推送内容

let content = UNMutableNotificationContent()
content.title = "Time Interval Notification" //推送内容标题
content.subtitle = "My first notification" //推送内容子标题
content.body = "My first notification"// 推送内容body
content.categoryIdentifier = "categoryIdentifier" //category标识,操作策略

2.设置通知触发器

有4种触发器
UNPushNotificationTrigger 触发APNS服务,系统自动设置(这是区分本地通知和远程通知的标识)
UNTimeIntervalNotificationTrigger 一段时间后触发
UNCalendarNotificationTrigger 指定日期触发
UNLocationNotificationTrigger 根据位置触发,支持进入某地或者离开某地或者都有。

//设置5秒后触发
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) //每周三,13点触发
var components:DateComponents = DateComponents()
components.weekday = 4;//周三
components.hour = 13;//13点
let triggerDateComponents = UNCalendarNotificationTrigger(dateMatching: components, repeats: true); //这个点,100米范围内,进入触发。
let Coordinate2:CLLocationCoordinate2D = CLLocationCoordinate2D(latitude: 39, longitude: 116);
let region:CLCircularRegion = CLCircularRegion(center: Coordinate2, radius: 100, identifier: "center")
region.notifyOnEntry = true;
region.notifyOnExit = false;
let triggerRegion = UNLocationNotificationTrigger(region: region, repeats: true);

3.添加通知

//先创建一个请求
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
//将请求添加到发送中心
UNUserNotificationCenter.current().add(request) { error in
if error == nil {
print("Time Interval Notification scheduled: \(requestIdentifier)")
}
}

APNS:Payload

iOS 10之前的推送内容比较单一,仅仅支持一段文字的消息推送,最好带上badge和sound,以及一些自定义的字段内容,而在iOS 10中,Apple丰富了推送内容,并且增加了更多的显示方式。

//iOS 10 之前的基础Payload:
{
"aps":{
"alert":{
"body": "This is a message"
},
"sound":"default",
"badge":1
}
}
//iOS 10 基础Payload:
{
"aps":{
"alert":{
"title":"I am title",
"subtitle":"I am subtitle",
"body":"I am body"
},
"sound":"default",
"badge":1
}
}

title和subtitle并不是必须的。

处理通知

常规处理

在创建通知请求时,我们已经指定了标识符。iOS10中我们可以通过标识符来管理处理通知。通UserNotificationKIt的一系列API 你可以做到: 查找更新删除通知。其中关键在于request的identifier,即在创建的时候的指定的通知的标识符。

查找通知
//获取所有等待递送的通知
UNUserNotificationCenter.current().getPendingNotificationRequests { (request) in
}
//获取所有已经递送的通知
UNUserNotificationCenter.current().getDeliveredNotifications { (noti) in
}
更新通知

远程推送可以进行通知的更新,在使用 center 的 addNotificationRequest:withCompletionHandler: 向 APNS提交请求时,在 HTTP/2 的 header 中 apns-collapse-id key 的内容将被作为该推送的标识符进行使用。多次推送同一标识符的通知即可进行更新。

//先创建一个请求
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
//重新添加通知
UNUserNotificationCenter.current().add(request) { error in
if error == nil {
print("Time Interval Notification scheduled: \(requestIdentifier)")
}
}
删除通知/取消通知
//使用这个API来移除通知 还有一系列相似的API
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: dentifiers)
//取消还未展示的本地通知
UNUserNotificationCenter.current().add(request) { error in
if error != nil {
print("Notification request added: \(identifier)")
}
}
delay(2) {
let newTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
let newRequest = UNNotificationRequest(identifier: identifier, content:newContent, trigger: newTrigger)
UNUserNotificationCenter.current().add(newRequest) { error in
if error != nil {
print("Notification request updated: \(identifier)")
}
}
}

通知的回调:UNUserNotificationCenterDelegate

UNUserNotificationCenterDelegate提供了两个方法处理通知。两个方法分别对应如何在应用内展示通知,和收到通知响应时要如何处理的工作。

//在应用内展示通知
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)
{
completionHandler([.alert, .sound]) // 如果不想显示某个通知,可以直接用空 options 调用 completionHandler:
// completionHandler([])
}
//对通知进行响应,收到通知响应时的处理工作,用户与你推送的通知进行交互时被调用;
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
completionHandler()
}

Notification Extension

iOS 10 中添加了很多 extension,作为应用与系统整合的入口。与通知相关的 extension 有两个:Service Extension 和 Content Extension。前者可以让我们有机会在「接收到推送之后、展示推送之前」对通知内容进行修改;后者可以用来自定义通知视图的样式。

Service Extension

Service Extension可以对推送进行处理,更改、替换原有的内容。他可以对通知内容进行加密,也可以给推送展示内容添加附件(比如照片、背景音乐),使得内容更加丰富。

//NotificationService 的模板已经为我们进行了基本的实现:
class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent? // 1 让你可以在后台处理接收到的推送,传递修改后的的内容给 contentHandler,然后展示
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
if request.identifier == "mutableContent" {
bestAttemptContent.body = "\(bestAttemptContent.body), onevcat"
}
contentHandler(bestAttemptContent)
}
} // 2 在在你获得的一小段运行代码的时间内没有调用 contentHandler 的话,系统会调用这个方法。可以在这里传肯定不会出错的内容,或者他会默认传递原始的推送内容。
override func serviceExtensionTimeWillExpire() {
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
contentHandler(bestAttemptContent)
}
}
}

Service Extension 现在只对远程推送APNS的通知起效,你可以在推送 payload 中增加一个 mutable-content 值为 1 的项来启用内容修改

{
aps : {
alert : "New Message",
mutable-content : 1
},
encrypted-content : "#myencryptedcontent"
}

Media Attachments

iOS 10 的另一个亮眼功能是多媒体的推送,开发者能够直接在推送的通知内容里面传递多媒体资源,在客户端进行直接的展示,极大丰富了推送内容的可读性和趣味性。

为本地通知添加添加多媒体内容

通过本地磁盘上的文件 URL 创建一个 UNNotificationAttachment 对象,然后将这个对象放到数组中赋值给 content 的 attachments 属性:

let content = UNMutableNotificationContent()
content.title = "Hey guys"
content.body = " body "
if let imageURL = Bundle.main.url(forResource: "image", withExtension: "jpg"),
let attachment = try? UNNotificationAttachment(identifier: "imageAttachment", url: imageURL, options: nil)
{
content.attachments = [attachment]
}
为远程推送添加多媒体内容

只需要在推送的 payload 中指定需要加载的资源地址,这个地址可以是应用 bundle 内已经存在的资源,也可以是网络的资源。不过因为在创建 UNNotificationAttachment 时我们只能使用本地资源,所以如果多媒体还不在本地的话,我们需要先将其下载到本地。在完成 UNNotificationAttachment 创建后,我们就可以和本地通知一样,将它设置给 attachments 属性,然后调用 contentHandler 了。

{
"aps":{
"alert":{
"title":"Image Notification",
"body":"Show me an image from web!"
},
"mutable-content":1 //表示我们会在接收到通知时对内容进行更改
},
"image": "https://img1.baidu.com.jpg"//指明了目标图片的地址
}
  • 如果你想在远程推送来的通知中显示应用 bundle 内的资源的话,要注意 extension 的 bundle 和 app main bundle 并不是一回事儿。你可以选择将图片资源放到 extension bundle 中,也可以选择放在 main bundle 里。总之,你需要保证能够获取到正确的,并且你具有读取权限的 url。
  • UNNotificationContent 的 attachments 虽然是一个数组,但是系统只会展示第一个 attachment 对象的内容。不过你依然可以发送多个 attachments,然后在要展示的时候再重新安排它们的顺序,以显示最符合情景的图片或者视频。

Notification Actions

iOS 8 和 9 中 Apple 引入了可以交互的通知,这是通过将一簇 action 放到一个 category 中,将这个 category 进行注册,最后在发送通知时将通知的 category 设置为要使用的 category 来实现的。这些action的API在iOS10 中被统一。

注册Actions
private func registerNotificationCategory() {
let saySomethingCategory: UNNotificationCategory = {
// 1 创建 action 即一项交互操作
let inputAction = UNTextInputNotificationAction(
identifier: "action.input",
title: "Input", // 是交互按钮的内容
options: [.foreground], // options 可以让该 action 成为一条可在前台执行的 action
textInputButtonTitle: "Send",
textInputPlaceholder: "What do you want to say...") let goodbyeAction = UNNotificationAction(
identifier: "action.goodbye",//,推送消息的其中的identifier
title: "Goodbye",
options: [.foreground]) let cancelAction = UNNotificationAction(
identifier: "action.cancel",
title: "Cancel",
options: [.destructive])
//2. 创建 category
return UNNotificationCategory(identifier:"saySomethingCategory", actions: [inputAction, goodbyeAction, cancelAction], intentIdentifiers: [], options: [.customDismissAction])
}()
// 3 把 category 添加到通知中心:
UNUserNotificationCenter.current().setNotificationCategories([saySomethingCategory])
}
// 4 触发方式
//远程通知触发方式
{
aps : {
alert : "Welcome to WWDC !",
category : "saySomethingCategory" //和第二步identifier:"saySomethingCategory一致
}
}
//本地通知触发方式 Local Notifications 只需要在创建 contnet 的时候指定 和第二步identifier 即可
content.categoryIdentifier = "saySomethingCategory";

通过上面的三个步骤我们已经创建了一个category

作者:曲年
链接:http://www.jianshu.com/p/567abab2098f
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

iOS10 推送通知详解(UserNotifications)的更多相关文章

  1. “iOS 推送通知”详解:从创建到设置到运行

    这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了视频讲解.本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义. 介绍一点点背景资料 ...

  2. iOS 远程推送通知 详解

    1: ios本地通知和远程通知 http://wangjun.easymorse.com/?p=1482 2: 苹果远程通知服务申请激活例图 (外国佬写的.) http://mobiforge.com ...

  3. iOS10 推送通知 UserNotifications

    简介 新框架 获取权限 获取用户设置 注册APNS,获取deviceToken 本地推送流程 远程推送流程 通知策略(Category+Action) 附件通知 代理回调 简介 iOS10新增了Use ...

  4. iOS10推送通知适配

    iOS10推送新增了UserNotifications Framework,使用起来其实很简单. 只是在iOS10以上系统上点击通知栏,回调方法不再走原来的这两个方法 - (void)applicat ...

  5. 【Android应用开发】 推送原理解析 极光推送使用详解 (零基础精通推送)

    作者 : octopus_truth 转载请注明出处 : http://blog.csdn.net/shulianghan/article/details/45046283 推送技术产生场景 : -- ...

  6. iOS-推送通知详解

    这是一篇编译的文章,内容均出自Parse.com的iOS开发教程,同时作者还提供了视频讲解.本文将带领开发者一步一步向着iOS推送通知的深处探寻,掌握如何配置iOS推送通知的奥义. 介绍一点点背景资料 ...

  7. Android开发之第三方推送JPush极光推送知识点详解 学会集成第三方SDK推送

    作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985 下面是一些知识点介绍,后期将会带领大家进行代码实战: 一.Android实现推送方式解决方案: 1.推 ...

  8. Xcode8开发iOS10推送通知过程

    iOS10发布后,简书优先开发增加了iOS10的新通知.本文分享整个feature的开发过程遇到的问题. 1.工程配置 Xcode8发生了很大的变化,直接打开原来的工程编译运行,这个时候是获取不到Pu ...

  9. centos7.2环境中kettle环境搭建及任务推送配置详解

    目标:将mysql5.5中testdb1的ehr_user表推送到tdoa的ehr_user表中,为避免不必要的麻烦,两张表结构.编码,包括数据库编码保持一致 操作系统:centos7.2 kettl ...

随机推荐

  1. Windows phone开发 网络编程之HttpWebRequest

    HttpWebRequest和WebClient的区别1,HttpWebRequest是个抽象类,所以无法new的,需要调用HttpWebRequest.Create();2,其Method指定了请求 ...

  2. vim的快捷键大全

    vim是开发利器,掌握快捷可以事半功倍,这里总结下常用的快捷键,提高开发速度这里写代码片 1.vim ~/.vimrc 进入配置文件 如果不知道vimrc文件在哪,可使用 :scriptnames 来 ...

  3. android黑科技系列——Android中新型安全防护策略

    一.前言 最近有一个同学,发给我一个设备流量访问检测工具,但是奇怪的是,他从GP上下载下来之后安装就没有数据了,而在GP上直接安装就可以.二次打包也会有问题.所以这里就可以判断这个app应该是有签名校 ...

  4. 几段Python小程序

    程序片段1 第一个需求是需要生成一些随机的时间,例如需要随机生成从一年前到现在的一些时间,刚开始折腾了半天,最后的代码如下: from datetime import timedelta from d ...

  5. 【原创】python中文编码问题深入分析(三):python2.7文件读写中文编码问题

    上一篇文章介绍和分析了python2.7中使用print遇到的中文编码问题的原因和解决方案,本篇主要介绍一下python2.7中执行文件读写可能遇到的编码问题. 1.文件读取 假如我们读取一个文件,文 ...

  6. Java中StringTokenizer类的使用

    StringTokenizer是一个用来分隔String的应用类,相当于VB的split函数. 1.构造函数 public StringTokenizer(String str) public Str ...

  7. Selenium3+python自动化-iframe

    一.frame和iframe区别 Frame与Iframe两者可以实现的功能基本相同,不过Iframe比Frame具有更多的灵活性. frame是整个页面的框架,iframe是内嵌的网页元素,也可以说 ...

  8. [系统资源]port range

    ip_local_port_range 端口范围 sysctl Linux中有限定端口的使用范围,如果我要为我的程序预留某些端口,那么我需要控制这个端口范围, 本文主要描述如何去修改端口范围. /pr ...

  9. Python之CSV模块

    1. CSV简介 CSV(Comma Separated Values)是逗号分隔符文本格式,常用于Excel和数据库的导入和导出,Python标准库的CSV模块提供了读取和写入CSV格式文件的对象. ...

  10. [luogu1129 ZJOI2007] 矩阵游戏 (二分图最大匹配)

    传送门 Description Input Output Sample Input 2 2 0 0 0 1 3 0 0 1 0 1 0 1 0 0 Sample Output No Yes HINT ...