如何在UNUserNotificationCenter触发通知时无操作调用函数?
解决方案:无需用户操作自动执行函数的重复通知实现
核心问题分析
你当前的代码仅在前台触发通知或用户点击通知时执行逻辑,但要实现「通知触发即自动调用函数(无需用户操作)」,需要分别处理前台和后台/锁屏两种场景。
一、前台场景:直接利用willPresent回调
当App处于前台时,通知触发会直接调用willPresent方法,无需用户操作,你可以直接在此处执行目标函数:
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void) { print("Foreground Notification IS CALLED") // 直接调用你需要执行的指定函数 executeTargetFunction() completionHandler([.badge, .banner, .sound]) } // 你的目标函数示例 private func executeTargetFunction() { print("通知触发,自动执行目标函数(前台)") // 这里添加你的业务逻辑 }
二、后台/锁屏场景:通过通知服务扩展实现
iOS默认不会在后台/锁屏且用户未操作时唤醒主App,但可以利用UNNotificationServiceExtension(通知服务扩展)在通知显示前短暂唤醒扩展进程,执行轻量级逻辑。
步骤1:添加通知服务扩展
- 打开Xcode → 点击
File→New→Target - 选择
Notification Service Extension,命名后完成创建(记得激活扩展)
步骤2:在扩展中实现自动执行逻辑
修改扩展的NotificationService.swift文件,在didReceive方法中调用目标函数:
class NotificationService: UNNotificationServiceExtension { var contentHandler: ((UNNotificationContent) -> Void)? var bestAttemptContent: UNMutableNotificationContent? override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { self.contentHandler = contentHandler bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) // 执行你的目标函数 executeTargetFunction() // 传递通知内容给系统(若不需要修改内容,直接传递即可) if let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } override func serviceExtensionTimeWillExpire() { // 扩展时间到期时必须调用contentHandler if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent { contentHandler(bestAttemptContent) } } private func executeTargetFunction() { print("通知触发,自动执行目标函数(后台/锁屏)") // 此处仅支持轻量级逻辑,避免耗时操作 } }
步骤3:修改本地通知配置
在createNotification方法中启用通知可变性,让通知经过服务扩展处理:
func createNotification() { let content = UNMutableNotificationContent() content.title = "Notification" content.subtitle = "Wow, Notification" content.categoryIdentifier = "Actions" content.sound = UNNotificationSound.defaultRingtone content.mutableContent = true // 新增:启用通知服务扩展 // 重复触发的通知建议用固定标识符,避免重复添加 let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 60, repeats: true) let request = UNNotificationRequest(identifier: "RepeatNotification", content: content, trigger: trigger) UNUserNotificationCenter.current().add(request) { error in if let error = error { print(error) } } }
三、额外优化点
- 通知分类仅需设置一次:将设置通知分类的代码移到App启动时(比如
AppDelegate的didFinishLaunchingWithOptions),避免重复执行:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { UNUserNotificationCenter.current().delegate = self let okay = UNNotificationAction(identifier: "Okay", title: "Okay", options: .destructive) let category = UNNotificationCategory(identifier: "Actions", actions: [okay], intentIdentifiers: [], options: []) UNUserNotificationCenter.current().setNotificationCategories([category]) return true }
- 固定通知标识符:重复触发的通知用固定标识符,避免多次添加导致重复通知。
内容的提问来源于stack exchange,提问作者Thushal Madhushanka
相关产品推荐
相关产品推荐

