Ios didReceiveRemoteNotification内部异步下载

Ios didReceiveRemoteNotification内部异步下载,ios,ajax,swift,apple-push-notifications,alamofire,Ios,Ajax,Swift,Apple Push Notifications,Alamofire,我的应用程序配置为支持静默推送(内容可用),还支持后台提取。我需要实现的是在收到静默推送后,我需要向服务器发送一个ajax请求,取回数据并保存它(用CoreData保存它) 当然,所有这些都是在用户从未打开应用程序的情况下发生的。当他打开应用程序时,新的数据将等待。这是无声的回拨: func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject],

我的应用程序配置为支持静默推送(内容可用),还支持后台提取。我需要实现的是在收到静默推送后,我需要向服务器发送一个ajax请求,取回数据并保存它(用CoreData保存它)

当然,所有这些都是在用户从未打开应用程序的情况下发生的。当他打开应用程序时,新的数据将等待。这是无声的回拨:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {

    // Use Alamofire to make an ajax call:
    //...
    let mutableURLRequest = NSMutableURLRequest(URL: URL)
    let requestBodyData : NSMutableData = NSMutableData()

    mutableURLRequest.HTTPBody = body
    mutableURLRequest.HTTPMethod = "POST"
    mutableURLRequest.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")
    mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")

    request(mutableURLRequest)
        .responseJSON { (req, res, data, error) in

            //We do not reach this code block !

            // Save the incoming data to CoreData
            completionHandler(UIBackgroundFetchResult.NewData)
    }
}
现在的问题是,当通知到达并调用委托时,ajax代码执行,调用服务器,然后退出。ajax回调中的代码将不会运行。但是,当我打开应用程序并将其置于前台时,此代码段突然苏醒并继续运行

这不是理想的行为,因为当我打开应用程序时,我仍然需要等待1-2秒,以便运行这些操作(更新UI等)

我做错了什么?我应该为此操作打开一个新的后台线程吗

更新:
我将completionHandler(UIBackgroundFetchResult.NewData)移动到ajax回调中,但这仍然不能解决最初的问题,即此ajax回调代码块不会执行

更新2:

这似乎是Alamofire的一个问题,我将不得不使用NSURLSession来进行这个ajax调用。正在尝试组合一些代码。

您没有正确使用“completionHandler”

调用此完成处理程序就像告诉iOS您已完成任务,它现在可以将您的应用程序恢复到睡眠或后台。你要马上打电话吗

所以你只需要把代码改成这样

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject], fetchCompletionHandler completionHandler: (UIBackgroundFetchResult) -> Void) {
    // Use Alamofire to make an ajax call:

    let mutableURLRequest = NSMutableURLRequest(URL: URL)
    let requestBodyData : NSMutableData = NSMutableData()

    mutableURLRequest.HTTPBody = body
    mutableURLRequest.HTTPMethod = "POST"
    mutableURLRequest.setValue("Bearer " + accessToken, forHTTPHeaderField: "Authorization")
    mutableURLRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")

    request(mutableURLRequest)
        .responseJSON { (req, res, data, error) in
            // if there was an error then {
            //     completionHandler(UIBackgroundFetchResult.Failed)
            //     return
            // }

            // Save the incoming data to CoreData
            completionHandler(UIBackgroundFetchResult.NewData)
    }
}
以下是关于该
completionHandler

下载操作完成时要执行的块。什么时候 调用此块,传入最能描述 下载操作的结果。您必须调用此处理程序并 我们应该尽快这样做。有关可能值的列表,请参见 UIBackgroundFetchResult类型

也有助于重写

您没有正确使用AlamoFire,但您可以将其配置为在后台状态下进行抓取:


完成处理程序应该在AF调用的完成块的末尾被调用,而不是在方法的开头被调用。

添加到此答案。当我这样做时,在
didReceiveMemoteNotification
之后启动后台获取时,我得到了零星的支持。我可以启动Alamofire连接,但它可能无法工作,它几乎会立即消失

浏览互联网和查看静默通知教程,似乎没有人提到:

  • beginBackgroundTaskWithExpirationHandler:
  • beginBackgroundTaskWithName(\:expirationHandler:)
  • endBackgroundTask(389;:)
大家都说,

是的,你在每个文档中大约有30秒的时间来完成你的工作,或者你需要使用NSURLSession后台会话

在我自己的测试和吹毛求疵中,为了给自己赢得30秒,您可能需要调用
UIApplicationDelegate上的
beginBackgroundTask*+endBackgroundTask
方法

参考资料:

:

具体来说,苹果开发者论坛的答案由苹果开发者关系部、开发者技术支持部、核心操作系统/硬件部的成员完成

他特别说:

嗯?您正在NSURLSession共享会话中发出请求。只有在应用程序保持运行时,此类请求才会运行。如果应用程序再次挂起(这通常是本例中发生的情况),请求将在中途停止。 这里有两个选项:

  • 继续使用共享会话,并使用UIApplication后台任务防止应用程序挂起。 这一点很重要,因为UIApplication后台任务通常只给您大约30秒的执行时间,所以请求必须完全快速地执行
  • 在NSURLSession后台会话中运行请求,该会话将在请求完成后组织恢复您的应用程序

注意第一个选项继续使用共享会话,并使用UIApplication后台任务来防止应用程序挂起。

OP并没有描述这一点。该方法通过完成处理程序,执行到底部,然后退出——请求正在发出。简单地说,您不能在挂起的线程上排队等待额外的后台工作,而期望它执行。如果一个方法在执行过程中被暂停,除非它超过了记录的30秒超时,这是没有意义的。@ BasZeN这个答案仍然有效。应用程序不应该简单地调用问题代码中所示的完成处理程序。它应该正确使用。@BaseZen它不只是在底部执行,它是在回调和数据下载后执行的,不理解你的downvoteb,因为它提出了事实上不正确的声明“你只需要做xyz…”我修正了completionHandler位置的更改,但这仍然不能解决原来的问题。嘿,你解决你的问题了吗?