Ios AFNetworking 3.0在应用程序移动到后台时继续上载
我的应用程序在前台启动向服务器上传内容。由于这个过程可能需要一些时间,用户可以很好地将应用程序转换到后台 我正在使用AFHTTPSessionManager提交上传:Ios AFNetworking 3.0在应用程序移动到后台时继续上载,ios,swift,afnetworking,afnetworking-3,Ios,Swift,Afnetworking,Afnetworking 3,我的应用程序在前台启动向服务器上传内容。由于这个过程可能需要一些时间,用户可以很好地将应用程序转换到后台 我正在使用AFHTTPSessionManager提交上传: let sessionManager = AFHTTPSessionManager() sessionManager.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-type") session
let sessionManager = AFHTTPSessionManager()
sessionManager.requestSerializer.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-type")
sessionManager.POST(urlStr, parameters: params, constructingBodyWithBlock: { (formData) -> Void in
formData.appendPartWithFileData(dataObject, name: "object", fileName: mimeType == "image/jpg" ? "pic.jpg" : "pic.mp4", mimeType: mimeType)
}, progress: { (progress) -> Void in
}, success: { (task, responseObject) -> Void in
print(responseObject)
success(responseObject: responseObject)
}, failure: { (task, error) -> Void in
print(error)
if let errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] as? NSData {
do {
let json = try NSJSONSerialization.JSONObjectWithData(errorData, options: NSJSONReadingOptions.MutableContainers)
failure(error: error, responseObject: json)
} catch let error {
print(error)
}
}
})
我需要在应用程序处于后台状态时继续此过程,直到完成。有一个很好的答案让我走上了正确的道路,但在某些地方我仍然一无所知。我尝试使用链接答案中的“BackgroundSessionManager”类将我的上传呼叫更改为:
BackgroundSessionManager.sharedManager().POST(NetworkManager.kBaseURLString + "fulfill_request", parameters: params, constructingBodyWithBlock: { (formData) -> Void in
formData.appendPartWithFileData(dataObject, name: "object", fileName: mimeType == "image/jpg" ? "pic.jpg" : "pic.mp4", mimeType: mimeType)
}, progress: nil, success: nil, failure: nil)?.resume()
并将此添加到我的AppDelegate:
func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: () -> Void) {
BackgroundSessionManager.sharedManager().savedCompletionHandler = completionHandler
}
但是我在一些后台线程上遇到了EXC_BAD_访问崩溃,几乎没有信息。我是否正确地处理了这个问题?一些观察结果:
内容类型
标题设置为应用程序/x-www-form-urlencoded
。但这不是多部分请求的有效内容头。我建议删除请求头的手动配置(或者告诉我们为什么这样做)。AFNetworking将为您设置内容类型
var backgroundTask = UIBackgroundTaskInvalid
func uploadImageWithData(dataObject: NSData, mimeType: String, urlStr: String, params: [String: String]?, success: (responseObject: AnyObject?) -> (), failure: (error: NSError, responseObject: AnyObject) -> ()) {
let app = UIApplication.sharedApplication()
let endBackgroundTask = {
if self.backgroundTask != UIBackgroundTaskInvalid {
app.endBackgroundTask(self.backgroundTask)
self.backgroundTask = UIBackgroundTaskInvalid
}
}
backgroundTask = app.beginBackgroundTaskWithName("com.domain.app.imageupload") {
// if you need to do any addition cleanup because request didn't finish in time, do that here
// then end the background task (so iOS doesn't summarily terminate your app
endBackgroundTask()
}
let sessionManager = AFHTTPSessionManager()
sessionManager.POST(urlStr, parameters: params, constructingBodyWithBlock: { (formData) -> Void in
formData.appendPartWithFileData(dataObject, name: "object", fileName: mimeType == "image/jpg" ? "pic.jpg" : "pic.mp4", mimeType: mimeType)
}, progress: { (progress) -> Void in
}, success: { (task, responseObject) -> Void in
print(responseObject)
success(responseObject: responseObject)
endBackgroundTask()
}, failure: { (task, error) -> Void in
print(error)
if let errorData = error.userInfo[AFNetworkingOperationFailingURLResponseDataErrorKey] as? NSData {
do {
let json = try NSJSONSerialization.JSONObjectWithData(errorData, options: NSJSONReadingOptions.MutableContainers)
failure(error: error, responseObject: json)
} catch let error {
print(error)
}
}
endBackgroundTask()
})
}
NSURLSession
内部处理中异步发生,这可能没有帮助,但这是我在试图追踪异常源时首先尝试的beginBackgroundTaskWithName
允许的三分钟),请注意后台任务必须是上载或下载任务
但是,我相信POST
方法将创建一个数据任务。在iOS 7中,根本不允许在后台会话中使用数据任务。在iOS 8中,您可以使用后台任务启动数据任务,但您必须使用NSURLSessionResponseBecomeDownload
响应didReceiverResponse
,例如,在BackgroundSessionManager
的configureDownloadFinished
中,您可以尝试添加:
[self setDataTaskDidReceiveResponseBlock:^NSURLSessionResponseDisposition(NSURLSession *session, NSURLSessionDataTask *dataTask, NSURLResponse *response) {
return NSURLSessionResponseBecomeDownload;
}];
NSURLRequest
对象,并将其作为上载或下载任务提交,而不是使用POST
。AFNetworking提供了将请求的构建和请求的提交解耦的机制,因此如果您需要沿着这条路走下去,请告诉我们,我们可以向您展示如何做到这一点总之,
beginBackgroundTaskWithName
比使用backgroundNSURLSession
更容易请求一点时间来完成请求。只有在绝对必要的情况下(例如,您很有可能需要三分钟以上才能完成请求),才可以执行后一种操作。非常感谢您如此彻底。我会尝试你提出的一些不同的建议,并发布一个更新。只是出于好奇,对于简单的背景任务,你的3分钟时间限制在哪里?苹果似乎对实际的时间限制非常模糊,但我在其他地方看到它可以支持10分钟。据我所知,任何地方都没有正式的文档记录,尽管我模糊地记得它在一个WWDC视频中被引用过。过去是10分钟,但现在是3分钟。如果你打电话,它会准确地告诉你有多少时间。再次感谢。最后使用了名为的BeginBackgroundTask。我们可能希望在将来使用后台会话,但更简单的方法效果很好。@Rob上传任务需要3分钟以上怎么办?我想上传视频到服务器的参数和使用AFNetworking。使用post、上传任务和数据任务方法。但系统只提供3分钟的上传时间。在此之后,应用程序将终止并停止上传。