从后台返回后,Alamofire 进度回调停止工作
Alamofire progress callback stops working after returning from background
我有一个上传(视频)数据到服务器的方法,它是这样的:
static func upload(video data:Data, named name:String, parameters:[String:Any], toUrl url:URL, progress:@escaping (Double)->Void, completion:@escaping(Bool)->Void){
manager = Alamofire.SessionManager(configuration: URLSessionConfiguration.background("com.app.backgroundtransfer")
manager.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(data, withName: "filedata", fileName: name, mimeType: "video/quicktime")
for key in parameters.keys{
if let val = parameters[key] as? String{
multipartFormData.append(val.data(using: .utf8, allowLossyConversion: false)!, withName: key)
}
}
}, to: url) {
(encodingResult) in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (uploadProgress) in
progress(uploadProgress.fractionCompleted)
//this one stops getting called
})
upload.responseJSON { response in
// but this one gets called at the end.
}
case .failure(let encodingError):
print(encodingError)
}
}
}
所以问题是,当从后台返回时(在上传过程中),我无法正确更新 UI。
为什么这个进度回调停止工作(从后台返回后)?
Alamofire 与后台会话并不真正兼容。由于它是基于闭包的 API,当应用程序进入后台时无法保留,因此当应用程序进入前台时,您的进度闭包不会重新连接。我们建议您直接使用 URLSession
或使用后台任务 API 而不是后台会话。
所以我所做的是使用后台任务(也完全没有 Alamofire 完成)并且它有效。像这样:
var backgroundTask: UIBackgroundTaskIdentifier = .invalid
func registerBackgroundTask() {
backgroundTask = UIApplication.shared.beginBackgroundTask {
self.endBackgroundTask()
}
assert(backgroundTask != .invalid)
}
func endBackgroundTask() {
print("Background task ended.")
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = .invalid
}
APIClient.manager = Alamofire.SessionManager(configuration: URLSessionConfiguration.background(withIdentifier: "com.app.backgroundtransfer"))
self.registerBackgroundTask()
APIClient.upload(video: video, named: videoDetailsModel.videoURL!.lastPathComponent, parameters: self.uploadParameters, toUrl: url, progress: {[weak self] (percentage) in
guard let `self` = self else {return}
print("Progress \(percentage)")
self.progressBar.progress = CGFloat(percentage)
}, completion: { [weak self] (success) in
guard let `self` = self else {return}
if(success){
print("Video successfully uploaded")
self.endBackgroundTask()
self.progressBar.progress = 1.0
}else{
print("Video upload was not successfull")
}
})
现在进度回调正常工作,您仍然可以像我使用的那样使用 Alamofire 打包 multipartformdata,或者出于任何原因使用它。
我有一个上传(视频)数据到服务器的方法,它是这样的:
static func upload(video data:Data, named name:String, parameters:[String:Any], toUrl url:URL, progress:@escaping (Double)->Void, completion:@escaping(Bool)->Void){
manager = Alamofire.SessionManager(configuration: URLSessionConfiguration.background("com.app.backgroundtransfer")
manager.upload(multipartFormData: { (multipartFormData) in
multipartFormData.append(data, withName: "filedata", fileName: name, mimeType: "video/quicktime")
for key in parameters.keys{
if let val = parameters[key] as? String{
multipartFormData.append(val.data(using: .utf8, allowLossyConversion: false)!, withName: key)
}
}
}, to: url) {
(encodingResult) in
switch encodingResult {
case .success(let upload, _, _):
upload.uploadProgress(closure: { (uploadProgress) in
progress(uploadProgress.fractionCompleted)
//this one stops getting called
})
upload.responseJSON { response in
// but this one gets called at the end.
}
case .failure(let encodingError):
print(encodingError)
}
}
}
所以问题是,当从后台返回时(在上传过程中),我无法正确更新 UI。
为什么这个进度回调停止工作(从后台返回后)?
Alamofire 与后台会话并不真正兼容。由于它是基于闭包的 API,当应用程序进入后台时无法保留,因此当应用程序进入前台时,您的进度闭包不会重新连接。我们建议您直接使用 URLSession
或使用后台任务 API 而不是后台会话。
所以我所做的是使用后台任务(也完全没有 Alamofire 完成)并且它有效。像这样:
var backgroundTask: UIBackgroundTaskIdentifier = .invalid
func registerBackgroundTask() {
backgroundTask = UIApplication.shared.beginBackgroundTask {
self.endBackgroundTask()
}
assert(backgroundTask != .invalid)
}
func endBackgroundTask() {
print("Background task ended.")
UIApplication.shared.endBackgroundTask(backgroundTask)
backgroundTask = .invalid
}
APIClient.manager = Alamofire.SessionManager(configuration: URLSessionConfiguration.background(withIdentifier: "com.app.backgroundtransfer"))
self.registerBackgroundTask()
APIClient.upload(video: video, named: videoDetailsModel.videoURL!.lastPathComponent, parameters: self.uploadParameters, toUrl: url, progress: {[weak self] (percentage) in
guard let `self` = self else {return}
print("Progress \(percentage)")
self.progressBar.progress = CGFloat(percentage)
}, completion: { [weak self] (success) in
guard let `self` = self else {return}
if(success){
print("Video successfully uploaded")
self.endBackgroundTask()
self.progressBar.progress = 1.0
}else{
print("Video upload was not successfull")
}
})
现在进度回调正常工作,您仍然可以像我使用的那样使用 Alamofire 打包 multipartformdata,或者出于任何原因使用它。