SessionManager
SessionManager 作為管理類,只做配置相關的設置,定義上傳、下載等功能的入口函數,具體功能的實現,數據的處理則下沉到其他相關類處理,使用非常簡潔,方便,容易理解
初始化
public static let `default`: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
}()
public init(
configuration: URLSessionConfiguration = URLSessionConfiguration.default,
delegate: SessionDelegate = SessionDelegate(),
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
self.delegate = delegate
self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
- 自定義
URLSessionConfiguration
的httpAdditionalHeaders
信息,有助于后臺阻止非法請求 -
URLSession
的代理移交給SessionDelegate
,達到任務分離的目的
后臺下載
后臺下載需要我們定義一個用于后臺下載的sessionManager
,這里我們包裝成一個單例
struct BackgroundManager {
static let shared = BackgroundManager()
let manager: SessionManager = {
let config = URLSessionConfiguration.background(withIdentifier: "com.alamofire.background")
config.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
config.sharedContainerIdentifier = "group.com.alamofire"
return SessionManager(configuration: config)
}()
}
下載代碼:
BackgroundManager.shared.manager.download(url) { (url, res) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in
let documentUrl = FileManager.default.urls(for: .documentationDirectory, in: .userDomainMask).first
let fileUrl = documentUrl?.appendingPathComponent(res.suggestedFilename!)
return (fileUrl!, [.removePreviousFile, .createIntermediateDirectories])
}
.downloadProgress { (progress) in
print("------\(progress)")
}
.response { (response) in
print("完成")
}
從下面的SessionManager.init
方法可以看到,sessionDelegate
實現了閉包sessionDidFinishEventsForBackgroundURLSession
private func commonInit(serverTrustPolicyManager: ServerTrustPolicyManager?) {
session.serverTrustPolicyManager = serverTrustPolicyManager
delegate.sessionManager = self
delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
guard let strongSelf = self else { return }
DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?() }
}
}
//sessionDelegate 后臺下載完成代理方法
open func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
sessionDidFinishEventsForBackgroundURLSession?(session)
}
delegate.sessionDidFinishEventsForBackgroundURLSession
會在session
后臺下載完成后執行,故而我們只要strongSelf.backgroundCompletionHandler
保存AppDelegate
授權后臺執行的閉包completionHandler
就可以了,即
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
BackgroundManager.shared.manager.backgroundCompletionHandler = completionHandler
}
如此,當后臺下載完成后,最終會回調執行系統的閉包completionHandler
如果最后不執行系統的completionHandler
,會有以下影響:
- 造成界面刷新卡頓
- 打印臺會輸出警告
Warning: Application delegate received call to -
application:handleEventsForBackgroundURLSession:completionHandler:
but the completion handler was never called.
執行結果:
當下載過程中,進入后臺,則會停止進度打印
進入后臺
當過一會回到前臺時,直接輸出完成,說明在后臺是在下載的
回到前臺