Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 从远程通知获取要在后台运行的方法_Ios_Swift_Firebase_Apple Push Notifications_Firebase Notifications - Fatal编程技术网

Ios 从远程通知获取要在后台运行的方法

Ios 从远程通知获取要在后台运行的方法,ios,swift,firebase,apple-push-notifications,firebase-notifications,Ios,Swift,Firebase,Apple Push Notifications,Firebase Notifications,我正在使用Firebase消息(通知)向iOS上的用户发送推送提醒。对于我的应用程序,这是一个待办事项应用程序,我使用的是Swift 3。当用户收到推送通知时,我希望他们能够直接从推送通知中完成任务 一切都很好。用户得到推送。当他们进行3d触摸时,他们会看到“完成按钮”。当点击“完成按钮”时,应用程序中的didReceive响应方法将在后台触发 现在来看问题,在该方法中,我使用闭包,然后在该闭包中使用闭包。出于某种原因,代码的第一部分在后台运行,用户不打开应用程序,但最后一部分仅在用户再次打开应

我正在使用Firebase消息(通知)向iOS上的用户发送推送提醒。对于我的应用程序,这是一个待办事项应用程序,我使用的是Swift 3。当用户收到推送通知时,我希望他们能够直接从推送通知中完成任务

一切都很好。用户得到推送。当他们进行3d触摸时,他们会看到“完成按钮”。当点击“完成按钮”时,应用程序中的didReceive响应方法将在后台触发

现在来看问题,在该方法中,我使用闭包,然后在该闭包中使用闭包。出于某种原因,代码的第一部分在后台运行,用户不打开应用程序,但最后一部分仅在用户再次打开应用程序时运行(见下文)。为什么呢

这是我的代码:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let userInfo = response.notification.request.content.userInfo

    if response.actionIdentifier == notificationActionComplete, let actionKey = userInfo["actionKey"] as? String {
        getAction(actionKey: actionKey, completion: { (action) in
            action.complete {

            }
        })
    }

    completionHandler()
}

func getAction(actionKey: String, completion:@escaping (Action)->Void) {
    Database.database().reference(withPath: "actions/\(actionKey)").observeSingleEvent(of: .value, with: { snapshot in
        let action = Action(snapshot: snapshot)
        completion(action)
    })
}
var ref: DatabaseReference?

init(snapshot: DataSnapshot) {
    key = snapshot.key
    ref = snapshot.ref

    //Other inits here
}

func complete(completion:@escaping (Void) -> Void) {
    //This code to remove the node is running fine in background
    ref.removeValue { (error, ref) in
        //The code in here is not running until the user opens the app next time
        otherRef.updateChildValues(self.toAnyObject(), withCompletionBlock: { (error, ref) in
        completion()        
    })
}
行动类:

func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
    let userInfo = response.notification.request.content.userInfo

    if response.actionIdentifier == notificationActionComplete, let actionKey = userInfo["actionKey"] as? String {
        getAction(actionKey: actionKey, completion: { (action) in
            action.complete {

            }
        })
    }

    completionHandler()
}

func getAction(actionKey: String, completion:@escaping (Action)->Void) {
    Database.database().reference(withPath: "actions/\(actionKey)").observeSingleEvent(of: .value, with: { snapshot in
        let action = Action(snapshot: snapshot)
        completion(action)
    })
}
var ref: DatabaseReference?

init(snapshot: DataSnapshot) {
    key = snapshot.key
    ref = snapshot.ref

    //Other inits here
}

func complete(completion:@escaping (Void) -> Void) {
    //This code to remove the node is running fine in background
    ref.removeValue { (error, ref) in
        //The code in here is not running until the user opens the app next time
        otherRef.updateChildValues(self.toAnyObject(), withCompletionBlock: { (error, ref) in
        completion()        
    })
}

在调用userNotificationCenter()的runloop循环之后,您的应用程序基本上处于暂停状态,因此,如果您的完成处理程序响应异步工作,则在应用程序再次恢复之前,该工作将永远不会发生。为了解决这个问题,您可能需要在该函数中开始一个后台任务,然后让您的完成处理程序在后台任务完成后结束它。这会告诉系统您需要在后台保持一段时间的活动状态(但如果您花费的时间太长,则无法保证)

请参阅此URL中的“执行有限限制任务”(抱歉,这是Obj-C,但也应该有一种快速的方法):


当到达未运行的代码时,程序是否会完全停止,或者只是跳过它并到达
用户通知中心(uuu:didReceiveResponse)
中的最终
completionHandler()
?您能否更新您的问题并显示
getAction
的声明?什么是
ref
?如何删除节点?您必须检查应用程序状态。您必须运行两个代码块,一个用于前台,另一个用于后台。代码似乎有点奇怪:完成后,底部的completionHandler将是对操作系统代码的回调。所以我通常在做完我所有的事情后再给它打电话。如果触发(延迟的)代码(在其他自定义完成处理程序中…),则必须传递它并在最后一段代码中执行它。否则你会告诉iOS:“我完了”,它认为你的任务完成了。