iOS 中的通知主要分爲 2 種,本地通知和遠程通知。git
UserNotifications
模塊。UNMutableNotificationContent
,能夠設置:(1)title:通知標題。 (2)subtitle:通知副標題。 (3)body:通知體。 (4)sound:聲音。 (5)badge:角標。 (6)userInfo:額外信息。 (7)categoryIdentifier:分類惟一標識符。 (8)attachments:附件,能夠是圖片、音頻和視頻,經過下拉通知顯示。 3. 指定本地通知觸發條件,有 3 種觸發方式: (1)UNTimeIntervalNotificationTrigger
:一段時間後觸發。 (2)UNCalendarNotificationTrigger
:指定日期時間觸發。 (3)UNLocationNotificationTrigger
:根據位置觸發。 4. 根據通知內容和觸發條件建立UNNotificationRequest
。 5. 將UNNotificationRequest
添加到UNUserNotificationCenter
。json
import UserNotifications
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 請求通知權限
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) { // 橫幅,聲音,標記
(accepted, error) in
if !accepted {
print("用戶不容許通知")
}
}
return true
}
複製代碼
import CoreLocation
import UIKit
import UserNotifications
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
// 一段時間後觸發
@IBAction func timeInterval(_ sender: Any) {
// 設置推送內容
let content = UNMutableNotificationContent()
content.title = "你好"
content.subtitle = "Hi"
content.body = "這是一條基於時間間隔的測試通知"
content.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "feiji.wav"))
content.badge = 1
content.userInfo = ["username": "YungFan", "career": "Teacher"]
content.categoryIdentifier = "testUserNotifications1"
setupAttachment(content: content)
// 設置通知觸發器
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
// 設置請求標識符
let requestIdentifier = "com.abc.testUserNotifications2"
// 設置一個通知請求
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
// 將通知請求添加到發送中心
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
// 指定日期時間觸發
@IBAction func dateInterval(_ sender: Any) {
// 設置推送內容
let content = UNMutableNotificationContent()
content.title = "你好"
content.body = "這是一條基於日期的測試通知"
// 時間
var components = DateComponents()
components.year = 2021
components.month = 5
components.day = 20
// 每週一上午8點
// var components = DateComponents()
// components.weekday = 2 // 週一
// components.hour = 8 // 上午8點
// components.minute = 30 // 30分
// 設置通知觸發器
let trigger = UNCalendarNotificationTrigger(dateMatching: components, repeats: false)
// 設置請求標識符
let requestIdentifier = "com.abc.testUserNotifications3"
// 設置一個通知請求
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
// 將通知請求添加到發送中心
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
// 根據位置觸發
@IBAction func locationInterval(_ sender: Any) {
// 設置推送內容
let content = UNMutableNotificationContent()
content.title = "你好"
content.body = "這是一條基於位置的測試通知"
// 位置
let coordinate = CLLocationCoordinate2D(latitude: 31.29065118, longitude: 118.3623587)
let region = CLCircularRegion(center: coordinate, radius: 500, identifier: "center")
region.notifyOnEntry = true // 進入此範圍觸發
region.notifyOnExit = false // 離開此範圍不觸發
// 設置觸發器
let trigger = UNLocationNotificationTrigger(region: region, repeats: true)
// 設置請求標識符
let requestIdentifier = "com.abc.testUserNotifications"
// 設置一個通知請求
let request = UNNotificationRequest(identifier: requestIdentifier, content: content, trigger: trigger)
// 將通知請求添加到發送中心
UNUserNotificationCenter.current().add(request, withCompletionHandler: nil)
}
}
extension ViewController {
func setupAttachment(content: UNMutableNotificationContent) {
let imageURL = Bundle.main.url(forResource: "img", withExtension: ".png")!
do {
let imageAttachment = try UNNotificationAttachment(identifier: "iamgeAttachment", url: imageURL, options: nil)
content.attachments = [imageAttachment]
} catch {
print(error.localizedDescription)
}
}
}
複製代碼
遠程通知是指在聯網的狀況下,由遠程服務器推送給客戶端的通知,又稱 APNs(Apple Push Notification Services)。在聯網狀態下,全部設備都會與 Apple 服務器創建長鏈接,所以無論應用是打開仍是關閉的狀況,都能接收到服務器推送的遠程通知。swift
UIApplication.shared.registerForRemoteNotifications()
向 APNs 請求 deviceToken。func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
獲取 deviceToken。若是正常獲取到 deviceToken,即表示註冊成功,能夠進行遠程通知的推送,最後須要將其發送給應用服務器。注意:
UIApplication.shared.registerForRemoteNotifications()
向 APNs 請求 deviceToken。func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data)
獲取 deviceToken。若是正常獲取到 deviceToken,即表示註冊成功,能夠進行遠程通知的推送,最後須要將其發送給應用服務器。Token Authentication 是 APNs 新推出的推送鑑權方式,它以下優點:api
(1)同一個開發者帳號下的全部 App 不管是測試仍是正式版都能使用同一個 Key 來發送而不須要爲每一個 App 生成證書。 (2)生成 Key 的過程相對簡單,不須要繁瑣的證書操做過程,而且它再也不有過時時間,無需像證書那樣須要按期從新生成。。服務器
import UserNotifications
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 請求通知權限
UNUserNotificationCenter.current()
.requestAuthorization(options: [.alert, .sound, .badge]) {
accepted, _ in
if !accepted {
print("用戶不容許通知。")
}
}
// 向APNs請求deviceToken
UIApplication.shared.registerForRemoteNotifications()
return true
}
// deviceToken請求成功回調
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
var deviceTokenString = String()
let bytes = [UInt8](deviceToken)
for item in bytes {
deviceTokenString += String(format: "%02x", item & 0x000000FF)
}
// 打印獲取到的token字符串
print(deviceTokenString)
// 經過網絡將token發送給服務端
}
// deviceToken請求失敗回調
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(error.localizedDescription)
}
}
複製代碼
注意:遠程通知不支持模擬器(直接進入deviceToken請求失敗回調),必須在真機測試。markdown
(1)證書方式須要:P12 證書 + Bundle Identifier + deviceToken。 (2)Token 方式須要:P8 AuthKey + Team ID + Key ID + Bundle Identifier + deviceToken。網絡
{
"aps":{
"alert":{
"title":"測試",
"subtitle":"遠程推送",
"body":"這是一條從遠處而來的通知"
},
"sound":"default",
"badge":1
}
}
複製代碼
xcrun simctl push booted developer.yf.TestUIKit /Users/yangfan/Desktop/playload.json
複製代碼
另外一種方法是將 APNs 文件直接拖到 iOS 模擬器中。準備一個後綴名爲.apns
的文件,其內容和上面的 JSON 文件差很少,可是添加了一個Simulator Target Bundle
,用於描述 App 的Bundle Identifier
。app
{
"Simulator Target Bundle": "developer.yf.TestUIKit",
"aps":{
"alert":{
"title":"測試",
"subtitle":"遠程推送",
"body":"這是一條從遠處而來的通知"
},
"sound":"default",
"badge":1
}
}
複製代碼
默認狀況下,App 只有在後臺才能收到通知提醒,在前臺沒法收到通知提醒,若是前臺也須要提醒能夠進行以下處理。異步
class NotificationHandler: NSObject, UNUserNotificationCenterDelegate {
// 前臺展現通知
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
// 前臺通知通常不設置badge
completionHandler([.list, .banner, .sound])
// 若是不想顯示某個通知,能夠直接用 []
// completionHandler([])
}
}
複製代碼
class AppDelegate: UIResponder, UIApplicationDelegate {
// 自定義通知回調類,實現通知代理
let notificationHandler = NotificationHandler()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 設置代理
UNUserNotificationCenter.current().delegate = notificationHandler
return true
}
}
複製代碼
// 手動添加角標
UIApplication.shared.applicationIconBadgeNumber = 10
// 清理角標
UIApplication.shared.applicationIconBadgeNumber = 0
複製代碼