Ios didReceiveRemoteNotification内部异步下载
我的应用程序配置为支持静默推送(内容可用),还支持后台提取。我需要实现的是在收到静默推送后,我需要向服务器发送一个ajax请求,取回数据并保存它(用CoreData保存它) 当然,所有这些都是在用户从未打开应用程序的情况下发生的。当他打开应用程序时,新的数据将等待。这是无声的回拨: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],
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;:)
UIApplicationDelegate上的beginBackgroundTask*+endBackgroundTask
方法
参考资料:
:
具体来说,苹果开发者论坛的答案由苹果开发者关系部、开发者技术支持部、核心操作系统/硬件部的成员完成
他特别说:
嗯?您正在NSURLSession共享会话中发出请求。只有在应用程序保持运行时,此类请求才会运行。如果应用程序再次挂起(这通常是本例中发生的情况),请求将在中途停止。
这里有两个选项:
- 继续使用共享会话,并使用UIApplication后台任务防止应用程序挂起。
这一点很重要,因为UIApplication后台任务通常只给您大约30秒的执行时间,所以请求必须完全快速地执行
- 在NSURLSession后台会话中运行请求,该会话将在请求完成后组织恢复您的应用程序
注意第一个选项继续使用共享会话,并使用UIApplication后台任务来防止应用程序挂起。OP并没有描述这一点。该方法通过完成处理程序,执行到底部,然后退出——请求正在发出。简单地说,您不能在挂起的线程上排队等待额外的后台工作,而期望它执行。如果一个方法在执行过程中被暂停,除非它超过了记录的30秒超时,这是没有意义的。@ BasZeN这个答案仍然有效。应用程序不应该简单地调用问题代码中所示的完成处理程序。它应该正确使用。@BaseZen它不只是在底部执行,它是在回调和数据下载后执行的,不理解你的downvoteb,因为它提出了事实上不正确的声明“你只需要做xyz…”我修正了completionHandler位置的更改,但这仍然不能解决原来的问题。嘿,你解决你的问题了吗?