美文网首页
Alamofire-后台下载及SessionManger流程分析

Alamofire-后台下载及SessionManger流程分析

作者: king_jensen | 来源:发表于2019-08-20 16:36 被阅读0次

我们在Alamofire-URLSession中讲到过URLSession实现的后台,我们用Alamofire实现后台下载。

Alamofire后台下载实现

 LGBackgroundManger.shared.manager
            .download(self.urlDownloadStr) { (url, response) -> (destinationURL: URL, options: DownloadRequest.DownloadOptions) in
            let documentUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first
            let fileUrl     = documentUrl?.appendingPathComponent(response.suggestedFilename!)
            return (fileUrl!,[.removePreviousFile,.createIntermediateDirectories])
            }
            .response { (downloadResponse) in
                print("下载回调信息: \(downloadResponse)")
            }
            .downloadProgress { (progress) in
                print("下载进度 : \(progress)")
        }

1.封装LGBackgroundManger后台下载管理类.
2.通过Block的方式实现下载进度的回调和下载完成方法的回调,不需要在实现代理方法。

struct LGBackgroundManger {
    
    static let shared = LGBackgroundManger()
    
    let manager: SessionManager = {
        let configuration = URLSessionConfiguration.background(withIdentifier: "com.alamofire.text")
        configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
        
        return SessionManager(configuration: configuration)
    }()
}

为什么要做成单例?
1.后台下载session的配置URLSessionConfiguration必须是background模式
2.如果不被持有,进入后台被释放,报错Error Domain=NSURLErrorDomain Code=-999 "cancelled"
3.可以达到应用层与网络层分离
4.方便在AppDelegate的回调直接接收completionHandler

Alamofire后台下载的流程和URLSession后台下载流程一样,需要在AppDelegate实现backgroundSessionCompletionHandler方法:

   var backgroundSessionCompletionHandler: (() -> Void)?
    
    func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {

        print("hello - \(identifier)")
        LGBackgroundManger.shared.manager.backgroundCompletionHandler = completionHandler
        self.backgroundSessionCompletionHandler = completionHandler
    }

那么我们还是有疑问,URLSession会在下载完成后urlSessionDidFinishEvents代理方法中,调用handleEventsForBackgroundURLSession保存的completionHandler达到下载后对屏幕的刷新。那么Alamofire是如何处理的?我们分析一下SessionManger的流程.

SessionManger流程分析

一、SessionManger的初始化
    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)
    }

1.configuration配置,如果没有指定默认URLSessionConfiguration.default
2.SessionDelegate = SessionDelegate(),将URLSession代理设置为SessionDelegate。代理移交给SessionDelegate。是一个重要的类,是多个代理的集合。
URLSessionTaskDelegate
URLSessionDataDelegate
URLSessionDownloadDelegate
URLSessionStreamDelegate
URLSessionDelegate

3.调用commonInit初始化信息。

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?() }
        }
    }

4.SessionDelegate保存sessionManager
这里sessionManager保存SessionDelegate,SessionDelegate也保存了sessionManager的引用,会有循环引用吗? SessionDelegateweak var sessionManager: SessionManager?保存SessionManagerweak修饰,所以不会造成循环引用.

5.为什么要在SessionDelegate中保存sessionManager?
(1)将sessionManager比作是一个经理,SessionDelegate比作是一个助理,经理分派任务给助理,助理处理任务,需要将处理结果反馈给经理。所以持有sessionManager的引用,就能方便的进行沟通。

二、下载完成回调

sessionManager将代理交给了SessionDelegate,当任务下载完成后,将会来到SessionDelegateurlSessionDidFinishEvents

 open func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
        sessionDidFinishEventsForBackgroundURLSession?(session)
    }

urlSessionDidFinishEvents调用sessionDidFinishEventsForBackgroundURLSession闭包,sessionDidFinishEventsForBackgroundURLSession是哪里初始化的?
我们找到了是在commonInit中初始化这个闭包

 delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
            guard let strongSelf = self else { return }
            DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?() }
        }

sessionDidFinishEventsForBackgroundURLSession中在主线程中调用sessionManager保存的backgroundCompletionHandler闭包。这个闭包就是AppDelegate调用handleEventsForBackgroundURLSession方法时,保存进去的。

三、总结
  1. sessionManager初始化时,在commonInit 方法中初始化``SessionDelegatesessionDidFinishEventsForBackgroundURLSession `闭包。
 delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
            guard let strongSelf = self else { return }
            DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?() }
        }

2.在appdelegate中的handleEventsForBackgroundURLSession方法中将返回的completionHandler保存到sessionManagerbackgroundCompletionHandler

  LGBackgroundManger.shared.manager.backgroundCompletionHandler = completionHandler

3.下载完成回调会来到SessionDelegateurlSessionDidFinishEvents

  open func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
        sessionDidFinishEventsForBackgroundURLSession?(session)
    }

4.urlSessionDidFinishEvents中调用1SessionDelegate保存的sessionDidFinishEventsForBackgroundURLSession
5.sessionDidFinishEventsForBackgroundURLSession中执行2中保存到sessionManager的闭包。

相关文章

  • Alamofire-后台下载及SessionManger流程分析

    我们在Alamofire-URLSession中讲到过URLSession实现的后台,我们用Alamofire实现...

  • Alamofire - Request

    上一篇 Alamofire-后台下载 其中就介绍了关于 SesssionManager 到 SessionDele...

  • Alamofire-后台下载

    系统后台下载 config三种模式defaultephemeral本文主角background 使用分片下载 官方...

  • Alamofire-后台下载

    这一篇主要讲解后台下载,后台下载对于应用程序来说,是一个非常重要也比较好用的功能。虽然用好后台下载的确能够大大提升...

  • Alamofire-后台下载

    上一篇文章提到了后台下载,下面看看在Alamofire中是如何处理后台下载的。首先使用原生写法来实现一个后台下载任...

  • Alamofire-后台下载

    1、枚举 HTTPMethod rawValue属性值关联 2、单例 SessionManager.default...

  • Alamofire-后台下载问题

    问题一 -999 被释放了,会报-999,所以可以确定URLSession.init是一个单例 问题二 掉帧 测试...

  • Alamofire 后台下载和流程分析

    前言 在开发中,为了提升用户体验常常会把下载大文件等网络请求放到后台下载,这样即使用户进入了后台,任务也能继续进行...

  • chip-seq数据分析流程

    chip-seq数据分析流程 1.chip-seq数据下载及更换名称 1.1.根据文献提供的ncbi的编号,下载s...

  • Alamofire-下载器

    一、suspend和resume Request的suspend Request的resume 总结 resume...

网友评论

      本文标题:Alamofire-后台下载及SessionManger流程分析

      本文链接:https://www.haomeiwen.com/subject/xosesctx.html