如何用Swift在iOS 11及以上版本编程创建持久化通知?
在iOS 11+中用Swift创建持久化通知
首先明确:在iOS 11及后续版本中,我们使用UserNotifications框架(iOS 10+引入)来管理通知,所谓“持久化通知”通常指用户无法通过常规滑动操作清除、需要应用主动移除的通知。下面是完整的实现步骤:
1. 导入框架并设置代理
首先在你的AppDelegate(或iOS 13+的SceneDelegate)中导入UserNotifications,并设置通知中心的代理:
import UIKit import UserNotifications @main class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 设置通知中心代理 UNUserNotificationCenter.current().delegate = self // 请求通知权限 requestNotificationPermissions() // 注册通知类别 registerNotificationCategories() return true } // 其他生命周期方法... }
2. 请求通知权限
要发送通知,首先需要向用户请求必要的权限:
private func requestNotificationPermissions() { let center = UNUserNotificationCenter.current() center.requestAuthorization(options: [.alert, .badge, .sound]) { granted, error in if let error = error { print("请求通知权限失败: \(error.localizedDescription)") } // 可根据权限授予状态做后续处理 } }
3. 注册持久化通知的类别
关键步骤:创建一个自定义通知类别,并设置options包含.customDismissAction——这样用户尝试清除通知时,系统会回调我们的代理方法,让我们决定是否允许清除:
private func registerNotificationCategories() { let center = UNUserNotificationCenter.current() // 创建自定义清除动作(供用户主动触发清除) let dismissAction = UNNotificationAction(identifier: "dismissAction", title: "清除通知", options: []) // 创建类别,设置.customDismissAction选项拦截默认清除行为 let persistentCategory = UNNotificationCategory(identifier: "PersistentNotificationCategory", actions: [dismissAction], intentIdentifiers: [], options: [.customDismissAction]) // 注册类别到通知中心 center.setNotificationCategories([persistentCategory]) }
4. 创建并发送持久化通知
构建通知内容并发送,注意要指定我们刚才注册的类别:
func sendPersistentNotification() { let center = UNUserNotificationCenter.current() // 构建通知内容 let content = UNMutableNotificationContent() content.title = "持久化通知" content.body = "这条通知无法被用户手动滑动清除" content.sound = .default // 指定关联的持久化类别 content.categoryIdentifier = "PersistentNotificationCategory" // 创建触发条件(这里用5秒后立即触发,也可设置时间/位置触发) let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 5, repeats: false) // 创建通知请求 let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger) // 添加请求到通知中心 center.add(request) { error in if let error = error { print("发送通知失败: \(error.localizedDescription)") } else { print("持久化通知已安排发送") } } }
5. 拦截用户的清除操作(保持通知持久化)
实现通知中心代理方法,当用户尝试清除通知时,我们可以阻止默认行为,让通知继续留在通知中心:
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) { // 拦截系统默认的清除动作 if response.actionIdentifier == UNNotificationDismissActionIdentifier { // 重新发送相同内容的通知,实现持久化效果 let content = response.notification.request.content.mutableCopy() as! UNMutableNotificationContent let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 0.1, repeats: false) let newRequest = UNNotificationRequest(identifier: response.notification.request.identifier, content: content, trigger: trigger) center.add(newRequest) } else if response.actionIdentifier == "dismissAction" { // 用户点击自定义清除按钮,允许移除通知 center.removeDeliveredNotifications(withIdentifiers: [response.notification.request.identifier]) } // 必须调用completionHandler结束回调 completionHandler() } // 可选:让通知在应用前台也能显示 func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { completionHandler([.alert, .sound]) }
注意事项
- iOS系统限制:即使做了上述设置,用户仍然可以通过“清除所有通知”来移除通知,这是系统级限制,开发者无法阻止。
- 持久化逻辑:这种方案主要是阻止用户单独滑动清除某条通知,必须通过应用提供的动作或系统的“清除所有”来移除。
- 测试建议:尽量在真机上测试,模拟器的通知行为可能和真机略有差异。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

