我正在一个新的应用程序中使用Alamofire(基于Alamofire的下载管理器示例),需要对使用后台会话下载文件进行一些澄清。
需要覆盖SessionDelegate才能使其正常工作吗?或者只需要使用backgroundCompletionHandler
?
通常,使用Alamofire在后台处理下载的步骤是什么?如何处理应用程序重新启动时仍有下载任务的情况?
我正在一个新的应用程序中使用Alamofire(基于Alamofire的下载管理器示例),需要对使用后台会话下载文件进行一些澄清。
需要覆盖SessionDelegate才能使其正常工作吗?或者只需要使用backgroundCompletionHandler
?
通常,使用Alamofire在后台处理下载的步骤是什么?如何处理应用程序重新启动时仍有下载任务的情况?
基于这篇精彩的教程,我制作了一个可在GitHub上获取的示例项目。它包含一个后台会话管理的示例。
根据苹果的URL Loading System编程指南:
在iOS和OS X中,当用户重新启动您的应用程序时,您的应用程序应立即创建与任何具有未完成任务的会话相同标识符的后台配置对象,然后为每个这些配置对象创建一个会话。这些新会话同样自动关联于正在进行的后台活动。
因此,通过使用适当的后台会话配置实例,您的下载将永远不会处于“流动”状态。
我还发现这个答案非常有帮助。
从Alamofire的GitHub页面:
应用程序可以为后台和短暂会话创建管理器,以及自定义默认会话配置的新管理器,例如用于默认标头(HTTPAdditionalHeaders)或超时间隔(timeoutIntervalForRequest)。
默认情况下,顶级方法使用具有默认会话配置的共享Manager
实例。但是,您可以像这样创建一个具有后台会话配置的管理器:
let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("com.example.app.background")
let manager = Alamofire.Manager(configuration: configuration)
Manager
实例进行请求。manager.startRequestsImmediately = true
let request = NSURLRequest(URL: NSURL(string: "your.url.here")!)
manager.request(request)
通过查看其实现,它还具有一个名为backgroundCompletionHandler
的属性,因此您可以添加完成块:
manager.backgroundCompletionHandler = {
// do something when the request has finished
}
编辑
使用 Alamofire 5 不再支持此功能,请查看发布说明:
不再支持使用带有后台标识符的 URLSessionConfiguration 。我们明确地确保 Alamofire 不与后台会话一起使用,以防止用户在支持和意外方面遇到持续的问题。
旧答案,如果您使用 Alamofire 4 仍然有效
实际上,使用 Alamofire 非常简单:
1)您的 Alamofire.Manager 应该配置一个后台会话标识符:
class NetworkManager {
...
private lazy var backgroundManager: Alamofire.SessionManager = {
let bundleIdentifier = ...
return Alamofire.SessionManager(configuration: URLSessionConfiguration.background(withIdentifier: bundleIdentifier + ".background"))
}()
...
}
2)在App Delegate中实现application(_:handleEventsForBackgroundURLSession:completionHandler:
并将完成处理程序传递给Alamofire.SessionManager.backgroundCompletionHandler
。
在我的情况下,AppDelegate方法如下:
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
NetworkManager.default.backgroundCompletionHandler = completionHandler
}
我的网络管理器有一个计算属性,用于设置Manager属性:
var backgroundCompletionHandler: (() -> Void)? {
get {
return backgroundManager.backgroundCompletionHandler
}
set {
backgroundManager.backgroundCompletionHandler = newValue
}
}
我搜索了很长时间才找到解决方案,直到读到上面提到的文章。对我来说问题在于 - 我必须启用外部附件通信。
其他所有操作都按照上述描述完成。 AppDelegate:
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
BackendAPIManager.sharedInstance.backgroundCompletionHandler = completionHandler
}
单例模式:
import Alamofire
class BackendAPIManager: NSObject {
static let sharedInstance = BackendAPIManager()
var alamoFireManager : Alamofire.SessionManager!
var backgroundCompletionHandler: (() -> Void)? {
get {
return alamoFireManager?.backgroundCompletionHandler
}
set {
alamoFireManager?.backgroundCompletionHandler = newValue
}
}
fileprivate override init()
{
let configuration = URLSessionConfiguration.background(withIdentifier: "com.url.background")
configuration.timeoutIntervalForRequest = 200 // seconds
configuration.timeoutIntervalForResource = 200
self.alamoFireManager = Alamofire.SessionManager(configuration: configuration)
}
}
BackendAPIManager.sharedInstance.alamoFireManager.upload(multipartFormData: { (multipartFormData) in ...