Ios Swift-收到静默通知后执行代码

Ios Swift-收到静默通知后执行代码,ios,swift,apple-push-notifications,Ios,Swift,Apple Push Notifications,在我的iOS应用程序中,我希望在收到Firebase发出的静默通知5秒钟后执行一段代码 暂定工作流程如下所示: func startTimer() { print("starting timer") if timer == nil { let task = UIApplication.shared.beginBackgroundTask(expirationHandler: nil) timer = DispatchSource

在我的iOS应用程序中,我希望在收到Firebase发出的静默通知5秒钟后执行一段代码

暂定工作流程如下所示:

func startTimer() {
    print("starting timer")
    if timer == nil {
        let task = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
        timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
        timer!.schedule(deadline: .now() + .seconds(5))
        timer!.setEventHandler {
            print("in event handler")
            self.deliveredNotifications()
            self.timer = nil
            UIApplication.shared.endBackgroundTask(task)
        }
        timer!.resume()
    }
    print("timer started")
}
  • 来自Firebase的静默通知到达设备=>OK
  • 应用程序提取一些数据并显示本地通知=>OK
  • 5秒钟后,我想列出通过
    UNUserNotificationCenter.current().getDeliveredNotifications
    =>发送的通知不正常
  • 在上述所有步骤中,没有用户干预,应用程序始终处于后台

    尝试的代码如下所示:

    //Receive the silent notification
    func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                         fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
        // Print message ID.
        if let messageID = userInfo[gcmMessageIDKey] {
            print("Message ID 2: \(messageID)")
        }
        showLocalNotification(userInfo: userInfo, fetchCompletionHandler: completionHandler)
    
        /* This was one of the attempts
        DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
            completionHandler(UIBackgroundFetchResult.newData)
        }
        */
    }
    
    //Show Local notification with the data received in silent notification
    func showLocalNotification(userInfo: [AnyHashable: Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {   
        let content = UNMutableNotificationContent()
        content.title = NSLocalizedString("notificationTitle", comment: "")
        content.body = NSLocalizedString("notificationBody", comment: "")
        content.userInfo = userInfo
    
        // Create the request
        let uuidString = UUID().uuidString
        let request = UNNotificationRequest(identifier: uuidString, content: content, trigger: nil)
                
        // Schedule the request with the system.
        let notificationCenter = UNUserNotificationCenter.current()
                
        notificationCenter.add(request) { (error) in
            if error != nil {
              // Handle any errors.
                print(error!)
            } else {
                self.startTimer()
                DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2)) {
                    completionHandler(UIBackgroundFetchResult.newData)
                }
    
                //completionHandler(UIBackgroundFetchResult.newData)
    
                /* This was another approach instead of using timer
                DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(5)) {
                    self.deliveredNotifications()
                }
                */
            }
        }
    }
    
    // Start timer to wait for 5 seconds
    func startTimer() {
        print("starting timer")
        if timer == nil {
            timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
            timer!.schedule(deadline: .now() + .seconds(5))
            timer!.setEventHandler {
                print("in event handler")
                self.deliveredNotifications()
                self.timer = nil
            }
            timer!.resume()
        }
        print("timer started")
    }
    
    //List notifications 
    func deliveredNotifications() {
        let notificationCenter = UNUserNotificationCenter.current()
        notificationCenter.getDeliveredNotifications(completionHandler:  { notifications -> () in
            print("in dispatch")
            print(notifications.count)
            for request in notifications {
                print(request.request.identifier)
            }           
        })
    }
    
    
    在上面的代码中,
    print(“在事件处理程序中”)
    永远不会在控制台上打印,因此
    deliveredNotifications()
    不会执行。
    startTimer()
    中的其他两条打印消息已成功打印

    但是,如果我在显示本地通知后直接调用
    deliveredNotifications()
    ,它将正常执行

    此外,如果我启动应用程序或发送另一个静默通知,则会执行计时器回调,但这不是所需的行为

    那么,我有没有遗漏什么,或者我能做些什么来让它工作呢

    我看到了一些类似的问题,但无法实现任何具体目标:


    假设您的应用程序支持后台任务,您可以尝试以下方法:

    func startTimer() {
        print("starting timer")
        if timer == nil {
            let task = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
            timer = DispatchSource.makeTimerSource(queue: DispatchQueue.global())
            timer!.schedule(deadline: .now() + .seconds(5))
            timer!.setEventHandler {
                print("in event handler")
                self.deliveredNotifications()
                self.timer = nil
                UIApplication.shared.endBackgroundTask(task)
            }
            timer!.resume()
        }
        print("timer started")
    }
    
    我认为主要原因是你没有启动后台任务,所以一旦你的应用程序进入后台,执行就会停止

    注意:如果超过允许的后台时间,您可能需要使用
    expirationHandler
    ,并执行一些错误处理