You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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:添加通知服务扩展

  1. 打开Xcode → 点击File → New → Target
  2. 选择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)
        }
    }
}

三、额外优化点

  1. 通知分类仅需设置一次:将设置通知分类的代码移到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
}
  1. 固定通知标识符:重复触发的通知用固定标识符,避免多次添加导致重复通知。

内容的提问来源于stack exchange,提问作者Thushal Madhushanka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 07:55:26