Alamofire-后台下载

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)
    }
  • 自定义URLSessionConfigurationhttpAdditionalHeaders信息,有助于后台阻止非法请求
  • 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.

执行结果:
当下载过程中,进入后台,则会停止进度打印


进入后台

当过一会回到前台时,直接输出完成,说明在后台是在下载的


回到前台

你可能感兴趣的:(Alamofire-后台下载)