介绍
借助iOS 10,tvOS 10和watchOS 3,Apple引入了一个称为UserNotifications框架的新框架。 这套全新的API提供了一种统一的,面向对象的方式,可以在这些平台上使用本地和远程通知。 与现有的API相比,此功能特别有用,因为现在与本地和远程通知的处理非常相似,并且不再仅通过词典来访问通知内容。
在本教程中,我将介绍这个新框架的基础知识,并展示如何轻松利用它来支持应用程序的通知。
本教程要求您使用最新的iOS,tvOS和watchOS SDK运行Xcode 8。
1.注册通知
任何支持通知的应用程序的第一步都是向用户请求权限。 与以前的iOS版本一样,在使用UserNotifications框架时,通常的做法是在应用程序启动完成后立即执行此操作。
在使用任何UserNotifications API之前,您需要将以下import语句添加到访问框架的任何Swift代码文件中:
import UserNotifications
接下来,为了注册您的应用程序以接收通知,您需要将以下代码添加到AppDelegate
的application(_:didFinishLaunchingWithOptions:)
方法中:
let center = UNUserNotificationCenter.current()
let options: UNAuthorizationOptions = [.alert, .badge, .sound]
center.requestAuthorization(options: options) { (granted, error) in
if granted {
application.registerForRemoteNotifications()
}
}
最初使用此代码,我们获得对当前UNUserNotificationCenter
对象的引用。 接下来,我们使用希望应用程序具有的通知功能来配置UNAuthorizationOptions
。 请注意,您可以在此处使用任意选项组合,例如, alert
或badge
和sound
。
然后使用这两个对象,通过在我们的UNUserNotificationCenter
实例上调用requestAuthorization(options:completionHandler:)
方法来为我们的应用请求显示通知的授权。 代码的完成处理程序块向其中传递了两个参数:
- 一个
Bool
值,表示用户是否授予了授权。 - 一个可选的
Error
对象,如果系统由于某种原因而无法为您的应用请求通知授权,它将包含信息。
请注意,注册远程通知将调用与以前的iOS版本相同的UIApplication
回调方法。 成功时, application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
将被调用,并application(_:didFailToRegisterForRemoteNotificationsWithError:)
将失败被调用。
2.安排通知
在本教程的这一部分中,我们将完全专注于使用UserNotifications框架安排本地通知。 由于引入了新框架,因此远程推送通知的发送未更改。
在计划之前,本地通知由UNNotificationRequest
类的实例表示。 此类型的对象由以下组件组成:
- 标识符:唯一的
String
,可让您将各个通知彼此区分开。 - 内容:
UNNotificationContent
对象,其中包含显示通知所需的所有信息,包括标题,副标题和应用徽章编号。 - 触发器:
UNNotificationTrigger
对象,系统使用它来确定何时将通知“发送”到您的应用。
首先,我们将研究可以为本地通知设置的各种类型的触发器。 UNNotificationTrigger
类是一个抽象类,这意味着您永远不要直接创建它的实例。 相反,您将使用可用的子类。 当前,UserNotifications框架为您提供了三个:
-
UNTimeIntervalNotificationTrigger
,它允许在计划通知后发送通知一段时间。 -
UNCalendarNotificationTrigger
,无论通知是在什么时间UNCalendarNotificationTrigger
,它都允许在特定的日期和时间发送通知。 -
UNLocationNotificationTrigger
,它允许在用户进入或离开指定地理区域时发送通知。
以下代码显示了如何创建每种类型的触发器:
let timeTrigger = UNTimeIntervalNotificationTrigger(timeInterval: 60.0 * 60.0, repeats: false)
var date = DateComponents()
date.hour = 22
let calendarTrigger = UNCalendarNotificationTrigger(dateMatching: date, repeats: true)
let center = CLLocationCoordinate2D(latitude: 40.0, longitude: 120.0)
let region = CLCircularRegion(center: center, radius: 500.0, identifier: "Location")
region.notifyOnEntry = true;
region.notifyOnExit = false;
let locationTrigger = UNLocationNotificationTrigger(region: region, repeats: false)
使用以上代码,已创建以下触发条件:
- 安排通知一小时后,
timeTrigger
将触发。 传递给UNTimeIntervalNotificationTrigger
初始化程序的timeInterval
参数以秒为单位。 -
calendarTrigger
将每天每天晚上10:00重复触发。 通过修改传递给UNCalendarNotificationTrigger
初始化程序的DateComponents
对象的其他属性,可以轻松更改触发器触发的确切日期和时间。 - 当用户到达指定坐标的500米以内(本例中为40°N 120°E)时,
locationTrigger
将触发。 从代码中可以看到,此触发类型可以用于任何坐标和/或区域大小,并且还可以在进入和退出区域时触发通知。
接下来,我们需要为通知创建内容。 这是通过创建UNMutableNotificationContent
类的实例来完成的。 必须使用此类,因为常规的UNNotificationContent
类具有对各种通知内容属性的只读访问权限。
以下代码显示了如何创建基本通知的内容:
let content = UNMutableNotificationContent()
content.title = "Notification Title"
content.subtitle = "Notification Subtitle"
content.body = "Some notification body information to be displayed."
content.badge = 1
content.sound = UNNotificationSound.default()
如果您希望获得完整的属性列表,请查看UNMutableNotificationContent
类参考 。
最后,我们现在只需要创建UNNotificationRequest
对象并安排它。 可以使用以下代码完成此操作:
let request = UNNotificationRequest(identifier: "LocalNotification", content: content, trigger: timeTrigger)
UNUserNotificationCenter.current().add(request) { error in
if let error = error {
// Do something with error
} else {
// Request was added successfully
}
}
最初使用此代码,我们通过将标识符,内容对象和触发器传递给初始化程序来创建请求对象。 然后,我们在当前UNUserNotificationCenter
对象上调用add(_:completionHandler:)
方法,并使用完成处理程序根据通知是否已正确调度来执行逻辑。
3.接收通知
使用UserNotifications框架时,处理传入的通知由您指定符合UNUserNotificationCenterDelegate
协议的对象处理。 该对象可以是您想要的任何对象,而不必像以前的iOS版本那样是应用程序委托。
不过,需要注意的一件事是,必须在应用程序完全启动之前设置委托。 对于iOS应用程序,这意味着您必须在application(_:willFinishLaunchingWithOptions:)
委托的application(_:willFinishLaunchingWithOptions:)
或application(_:didFinishLaunchingWithOptions:)
方法内分配委托。 使用以下代码可以非常轻松地为用户通知设置委托:
UNUserNotificationCenter.current().delegate = delegateObject
现在已经设置了委托,当应用程序收到通知时,您只需要担心两种方法。 这两个方法都传递了一个UNNotification
对象,该对象表示正在接收的通知。 该对象包含一个date
属性和一个request
属性,该属性可以准确地告诉您通知的发送时间,而request
属性是前面提到的UNNotificationRequest
类的实例。 从此请求对象,您可以访问通知的内容以及(如果需要)通知的触发器。 该触发对象将是前面提到的UNNotificationTrigger
子类之一的实例,或者在推送通知的情况下,将是UNPushNotificationTrigger
类的实例。
由UNUserNotificationCenterDelegate
协议定义的第一个方法是userNotificationCenter(_:willPresent:withCompletionHandler:)
方法。 仅当您的应用程序在前台运行并收到通知时才调用此方法。 从这里,您可以访问通知的内容,并在需要时在应用程序中显示自己的自定义界面。 另外,您可以告诉系统使用各种选项来显示通知,就像您的应用程序未运行时一样。 可用的选项有:
- 警报以显示系统生成的通知界面
- 声音播放与通知相关的声音
- 徽章,可在用户主屏幕上编辑您的应用的徽章
以下代码显示了userNotificationCenter(_:willPresent:withCompletionHandler:)
方法的示例实现:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
let content = notification.request.content
// Process notification content
completionHandler([.alert, .sound]) // Display notification as regular alert and play sound
}
由UNUserNotificationCenterDelegate
协议定义的另一种方法是userNotificationCenter(_:didReceive:withCompletionHandler:)
方法。 当用户以任何方式与您的应用通知进行交互(包括关闭通知或从中打开您的应用)时,都会调用此方法。
该方法具有一个UNNotificationResponse
对象作为参数传递给它,而不是UNNotification
对象。 该对象包含代表已传递的通知的UNNotification
对象。 它还包括一个actionIdentifier
属性,用于确定用户如何与通知进行交互。 在取消通知或打开您的应用程序的情况下,UserNotifications框架会提供恒定的动作标识符供您比较。
以下代码显示了userNotificationCenter(_:didReceive:withCompletionHandler:)
方法的示例实现:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let actionIdentifier = response.actionIdentifier
switch actionIdentifier {
case UNNotificationDismissActionIdentifier: // Notification was dismissed by user
// Do something
completionHandler()
case UNNotificationDefaultActionIdentifier: // App was opened from notification
// Do something
completionHandler()
default:
completionHandler()
}
}
请注意,对于这两个委托方法,在完成处理通知后立即调用完成处理程序是至关重要的。 完成后,系统便知道您已经完成了通知,并可以执行任何所需的过程,例如将通知放在用户的通知中心中。
4.管理通知
有时,您的应用程序用户可能会在您的应用程序未运行时收到多个通知。 他们还可能直接从主屏幕而不是通过通知打开您的应用。 在这两种情况下,都不会调用UNUserNotificationCenterDelegate
协议方法。 使用本地通知时,有时您可能还希望删除计划的通知,然后再将其显示给用户。
因此,UserNotifications框架在当前的UNUserNotificationCenter
实例上提供以下方法,以处理未处理的本地通知和尚未处理的已传递通知:
-
getPendingNotificationRequests(completionHandler:)
在完成处理程序中为您提供一组UNNotificationRequest
对象。 该数组将包含您已调度的所有尚未触发的本地通知。 -
removePendingNotificationRequests(withIdentifiers:)
删除所有计划的本地通知,这些通知带有作为参数传入的String
数组中包含的标识符。 -
removeAllPendingNotificationRequests
删除应用程序的所有计划的本地通知。 -
getDeliveredNotifications(completionHandler:)
在完成处理程序中为您提供了一组UNNotification
对象。 该数组将包含为您的应用程序传递的所有通知,这些通知仍在用户的通知中心中显示。 -
removeDeliveredNotifications(withIdentifiers:)
删除所有传递的通知,这些通知具有从用户的通知中心传入的String
数组中包含的标识符。 -
removeAllDeliveredNotifications
删除应用程序的所有已传递通知。
5.自定义操作通知
UserNotifications框架还使您的应用更容易利用iOS 8中引入的自定义通知类别和操作。
首先,您需要分别使用UNNotificationAction
和UNNotificationCategory
类定义应用程序支持的自定义操作和类别。 对于您希望用户能够输入文本的操作,可以使用UNTextInputNotificationAction
类,它是UNNotificationAction
的子类。 定义动作和类别后,您只需在当前UNUserNotificationCenter
实例上调用setNotificationCategories(_:)
方法。 以下代码显示了如何轻松地在自己的应用程序中为消息类别通知注册回复和删除操作:
let replyAction = UNTextInputNotificationAction(identifier: "com.usernotificationstutorial.reply", title: "Reply", options: [], textInputButtonTitle: "Send", textInputPlaceholder: "Type your message")
let deleteAction = UNNotificationAction(identifier: "com.usernotificationstutorial.delete", title: "Delete", options: [.authenticationRequired, .destructive])
let category = UNNotificationCategory(identifier: "com.usernotificationstutorial.message", actions: [replyAction, deleteAction], intentIdentifiers: [], options: [])
center.setNotificationCategories([category])
接下来,当用户使用您的自定义通知动作之一时,将调用我们前面介绍的同一userNotificationCenter(_:didReceive:withCompletionHandler:)
方法。 在这种情况下,传入的UNNotificationResponse
对象的操作标识符将与您为自定义操作定义的标识符相同。 还需要注意的是,如果用户与文本输入通知动作进行了交互,则传递给此方法的响应对象将为UNTextInputNotificationResponse
类型。
以下代码显示了此方法的示例实现,包括先前创建的操作的逻辑:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
let actionIdentifier = response.actionIdentifier
let content = response.notification.request.content
switch actionIdentifier {
case UNNotificationDismissActionIdentifier: // Notification was dismissed by user
// Do something
completionHandler()
case UNNotificationDefaultActionIdentifier: // App was opened from notification
// Do something
completionHandler()
case "com.usernotificationstutorial.reply":
if let textResponse = response as? UNTextInputNotificationResponse {
let reply = textResponse.userText
// Send reply message
completionHandler()
}
case "com.usernotificationstutorial.delete":
// Delete message
completionHandler()
default:
completionHandler()
}
}
此外,如果您想利用本地通知的自定义操作,则可以在创建通知时简单地在UNMutableNotificationContent
对象上设置categoryIdentifier
属性。
结论
新的UserNotifications框架提供了功能齐全且易于使用的面向对象的API,用于在iOS,watchOS和tvOS上处理本地和远程通知。 它使在各种情况下安排本地通知变得非常容易,并且大大简化了处理传入通知和自定义操作的整个流程。
翻译自: https://code.tutsplus.com/tutorials/an-introduction-to-the-usernotifications-framework--cms-27250