iOS Local Notifications 本地推播
推播通知 (Push Notification) 分為兩種:「本地 (Local)」和「遠端 (Remote)」。本地通知是由 App 自己發出的(例如鬧鐘),不需要架設伺服器。
請求權限
所有通知都必須先獲得使用者同意。
import UserNotifications
func requestPermission() {
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in
if granted {
print("使用者同意通知")
} else {
print("使用者拒絕通知")
}
}
}
發送通知
發送通知包含三個部分:內容 (Content)、觸發條件 (Trigger) 和 請求 (Request)。
func scheduleNotification() {
// 1. 內容
let content = UNMutableNotificationContent()
content.title = "喝水時間到了"
content.body = "該起來走動一下囉!"
content.sound = .default
// 群組功能:相同 ID 的通知會被疊在一起
content.threadIdentifier = "health-reminder"
// 2. 觸發條件 (例如 5 秒後)
let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false)
// 3. 建立請求
let request = UNNotificationRequest(identifier: "water_reminder", content: content, trigger: trigger)
// 4. 加入排程
UNUserNotificationCenter.current().add(request)
}
可互動通知 (Actionable Notifications)
你可以讓使用者直接在通知上點擊按鈕,而不需要打開 App。
func registerActions() {
// 定義動作
let drinkAction = UNNotificationAction(identifier: "ACTION_DRINK", title: "我喝了", options: [])
let laterAction = UNNotificationAction(identifier: "ACTION_LATER", title: "稍後提醒", options: [])
// 定義分類
let category = UNNotificationCategory(identifier: "WATER_CATEGORY", actions: [drinkAction, laterAction], intentIdentifiers: [])
// 註冊
UNUserNotificationCenter.current().setNotificationCategories([category])
}
// 在發送通知時指定 categoryIdentifier
content.categoryIdentifier = "WATER_CATEGORY"
管理通知
你可以取消尚未發出的通知,或移除已經顯示在通知中心的通知。
// 取消特定 ID 的待發送通知
UNUserNotificationCenter.current().removePendingNotificationRequests(withIdentifiers: ["water_reminder"])
// 移除通知中心裡已顯示的通知
UNUserNotificationCenter.current().removeDeliveredNotifications(withIdentifiers: ["water_reminder"])
在前景收到通知
預設情況下,App 在前景執行時不會跳出通知橫幅。如果你希望在前景也能顯示,需要實作 UNUserNotificationCenterDelegate。
class AppDelegate: NSObject, UIApplicationDelegate, UNUserNotificationCenterDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
UNUserNotificationCenter.current().delegate = self
return true
}
// 讓通知在前景也能顯示
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound, .badge])
}
}