Session 710 : What’s New in User Notifications
iOS 10 新增的 UserNotifications.framework 用一套易用的接口替换了之前版本杂乱的接口,是一次通知接口的大重构。而 iOS 12 则从用户体验的角度为通知带来了诸如通知分类等便捷的新特性, 通知内容扩展也在此次更新中获得了更强的交互能力。本文也从这两个方面对 iOS 12 通知特性的变更进行介绍。
新增特性
1. 应用通知分组( Grouped Notifications )
iOS 12 中同一类型的通知会被合成一个通知组,用户可以通过点击通知组展开组里的所有通知。
通知分组使用两种分组方式:自动分组( Automatic grouping ) 和线程标识( Thread identifier )。开发者不需要对自动分组做额外的操作,系统会根据 App 的 bundle id 对推送进行分组。如果需要对通知做更细致的分组就需要用上线程标识了。// 本地通知
let content = UNMutableNotificationContent()
content.title = "New Photo"
content.body = "Jane Doe posted a new photo"
// 自定义标识
content.threadIdentifier = "thread-identifier"
// 远程通知
{
"aps" : {
"alert" : {
"title" : "New Photo",
"body" : "Jane Doe posted a new photo",
"thread-id" : "thread-identifier",
}
}
}
用户可以在通知管理页面对通知分组进行管理:
- 自动( Automatic )
- 按应用( By App )
- 关闭( Off ) 注:如果用户选择了 按应用 分组,系统会无视你设定的线程标识只通过 bundle id 对通知进行分组。
2. 通知中心新增通知管理界面
由于现在的用户管理单个应用通知设置的入口太深,iOS 12 推出了全新的推送管理页面以便用户更快捷的操作。
在新的通知管理页面中我们可以看到两个明显的按钮:隐式推送( Deliver Quietly ) 和 关闭( Turn Off ) 。 隐式推送(根据用户行为有时展示为显式推送)是 iOS 12 为方便用户对通知设置的两种便捷模式之一:- 隐式推送(Deliver Quietly) 隐式推送只会显示在通知中心,不会带有声音提醒,应用角标。
- 显式推送(Deliver Prominently) 显示推送会开启所有的通知选项。
展示管理页面有 3 种方式:
- 左滑通知,点击 管理 按钮
- 进入通知详情页面,点击右上角的 更多 按钮
- 系统根据用户行为自动的给出提示,点击 管理 按钮
自定义通知设置页面( Custom Settings )
由于新的通知管理页面也支持用户关闭通知提示,App 可以为通知提供更详细的管理页面引导用户关闭部分他们不希望收到的推送而不是关闭所有。当用户点击通知设置页面对应的按钮时,iOS 12 提供了新的代理方法获取这个事件并处理。 注:代理中 notification 参数是个 optional ,当用户从设置页面点击管理通知时这个参数会是 nil 。
import UIKit
import UserNotifications
class AppDelegate: UIApplicationDelegate, UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, openSettingsFor notification: UNNotification? ) {
}
}
3. 无需用户授权也能给用户推送的新机制:临时授权( Provisional Authorization )
iOS 12 提供了一种新的通知授权机制:临时授权。这种机制不会给用户授权的弹窗而直接尝试给用户推送,需要注意的是临时授权推送的消息只会以隐式推送的方式展示给用户。
在代码中我们只需要设置参数 provisional 就能使用这种机制。
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.requestAuthorization(options:[.badge, .sound, .alert, .provisional]) {
}
4. 勿扰模式下依然可以收到的通知:重要提醒( Critical Alerts )
当我们在开会或者参与一些很重要的活动时,通常会开启勿扰模式或者关闭铃声,但这个操作有可能会让我们错过一些关键的通知。 iOS 12 中加入的重要提醒能够无视勿扰模式和铃声开关的限制,收到这类通知时会伴随一个系统或 App 设定的提示音。需要推送重要提醒的应用需要前往 developer.apple.com/contact/req… 获得授权。
注:所谓的重要提醒是指那些需要用户即刻做出反应的通知,例如与医疗和健康相关的通知,与家庭安全相关的通知,与公共安全相关的通知等。
通知设置页面重要提醒的开关区别于普通的通知开关
系统允许只接收重要提醒在代码中我们需要设置参数 criticalAlert ,用户会看到单独的重要提醒授权
let notificationCenter = UNUserNotificationCenter.current()
notificationCenter.requestAuthorization(options:[.badge, .sound, .alert, .criticalAlert]) {
}
推送重要提醒通知和普通通知的区别在于提示音
// 本地重要提醒
let content = UNMutableNotificationContent()
content.title = "WARNING: LOW BLOOD SUGAR"
content.body = "Glucose level at 57."
content.categoryIdentifier = "low-glucose—alert"
// 使用系统默认的重要提醒音
content.sound = UNNotificationSound.defaultCritical
// 使用自定义的重要提醒音
content.sound = UNNotificationSound.criticalSoundNamed(@"warning-sound" withAudioVolume: 1.00)
// 远程重要提醒
{
"aps" : {
"sound" : {
"critical": 1,
"name": "warning-sound.aiff",
"volume": 1.0
}
}
}
旧有特性升级
1. 通知内容扩展升级,更具交互性( Notification Content Extensions )
Notification Content Extensions 是 iOS 10 新增的通知扩展之一,在 iOS 12 中得到了增强,不熟悉的同学可以通过喵神的文章了解下: 活久见的重构 - iOS 10 UserNotifications 框架解析。
通知动作( notification actions )
iOS 12 提供了新的 API 来解决动作当前动作存在的两个问题:
- 无法动态修改
- 与 category 联系紧密
extension NSExtensionContext {
@available(iOS 12.0, *)
var notificationActions: [UNNotificationAction]
}
notificationActions 属性允许你获取当前扩展的动作,更新新的动作。
class NotificationViewController: UIViewController, UNNotificationContentExtension {
func didReceive(_ response: UNNotificationResponse, completionHandler completion:
(UNNotificationContentExtensionResponseOption) -> Void) {
if response.actionIdentifier == "like-action" {
// Update state...
let unlikeAction = UNNotificationAction(identifier: "unlike-action", title: "Unlike", options: [])
let currentActions = extensionContext?.notificationActions
let commentAction = currentActions![1]
let newActions = [ unlikeAction, commentAction ]
extensionContext?.notificationActions = newActions
}
}
}
通知扩展界面新增可交互状态( User interaction )
Content view 是默认不可交互的,iOS 12 想要将其设置为可交互的状态,只需要在 plist 中 将 UNNotificationExtensionUserInteractionEnabled 设置为 true 即可。通过 API 调用启动 App( Launch application )
某些场景下我们会在通知内容扩展中加入展示所有评论的功能,并且展示操作只有在应用内才能完成,iOS 12 提供了一个新的 API 让我们能通过代码启动 App 。
extension NSExtensionContext {
@available(iOS 12.0, *)
func performNotificationDefaultAction()
}
// Demo: 在 Notification Content Extension 中启动 App
import UserNotificationsUI
class NotificationViewController: UIViewController, UNNotificationContentExtension {
@IBOutlet var allCommentsButton: UIButton?
...
allCommentsButton?.addTarget(self, action: #selector(launchApp), for: .touchUpInside)
...
@objc func launchApp() {
extensionContext?.performNotificationDefaultAction()
}
}
当这个 API 被调用时, App 会被启动,并调用代理方法:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void) {
// Handle action response
}
通过 API 调用隐藏通知内容扩展界面( Dismiss content extension view )
如果我们想在通知内容扩展上增加一个‘喜欢’按钮,用户点击后自动关闭当前的扩展,新增加的 API 能够帮助你实现这一功能。
extension NSExtensionContext {
@available(iOS 12.0, *)
func dismissNotificationContentExtension()
}
// Demo: 在通知内容扩展中隐藏通知内容扩展页面
import UserNotificationsUI
class NotificationViewController: UIViewController, UNNotificationContentExtension {
@IBOutlet var likeButton: UIButton?
...
likeButton?.addTarget(self, action: #selector(likeButtonTapped), for: .touchUpInside)
...
@objc func likeButtonTapped() {
likedPhoto()
extensionContext?.dismissNotificationContentExtension()
}
}
需要注意的是,调用这个 API 并不会移除那条通知,如果需要移除通知可以调用下面的 API
class UNUserNotificationCenter {
func removeDeliveredNotifications(withIdentifiers identifiers: [String])
}
总结
有 iOS 10 整体通知框架的打底,iOS 12 在通知的用户体验上的提升还是挺显著的,而通知关闭的成本降低势必需要内容生产方对推送内容更加谨慎,或者为部分推送内容提供关闭的选项。期待在 iOS 12 上看到利用新特性的有趣应用。
查看更多 WWDC 18 相关文章请前往 老司机x知识小集xSwiftGG WWDC 18 专题目录 - 简书