Alamofire(三)後臺下載原理

Alamofire學習(一)網絡基礎git

Alamofire(二)URLSessiongithub

Alamofire(三)後臺下載原理swift

@TOCapi

  • 前面兩篇博客:alamofire(一)網絡基礎alamofire(二) URLSession 分別講解了alamofire框架實現所需的一些必備的網絡基礎知識和iOS 系統網絡框架Api。屬性這些知識後,咱們再來探索alamofire框架的設計思想和底層實現就事半功倍了。本篇博客主要講解Alamofire的一個重要功能「後臺下載」的實現原理。
  • 咱們先來回顧一下alamofire(一)網絡基礎這篇博客留下的一個彩蛋:

alamofire框架簡介
從這個結構圖裏面咱們能夠大體瞭解一下Alamofire框架主要涉及哪些方面的知識。總的來講alamofire是一個很是牛逼的網絡框架,它是AFNetwork的父親開發的,在github上面有3萬多個星星,足以證實他是多麼的牛B。很是值得咱們深刻研究。

URLSession後臺下載

  • 在上一篇博客 alamofire(二) URLSession 已經大體的講解了一些URLSession後臺下載的流程和實現代碼。這裏再來回顧總結一下,有利於更好的理解Alamofire框架後臺下載的原理。

URLSession後臺流程

URLSession實現後臺下載的步驟以下圖:markdown

URLSession實現後臺下載的步驟
如上圖6步就能夠實現後臺下載,其實代碼實現起來也很簡單。

  • 上圖的1-3步能夠因爲代碼比較簡單能夠合在一塊兒講,具體就是:首先初始化一個 background 的模式的 configuration。configuration有 三種模式 ,只有background 的模式才能進行後臺下載。 而後,經過configuration初始化網絡下載會話 session,設置相關代理,回調數據信號響應。 最後,session建立downloadTask任務-resume啓動 (默認狀態:suspend),具體代碼以下:
// 1:初始化一個background的模式的configuration
let configuration = URLSessionConfiguration.background(withIdentifier: self.createID())
// 2:經過configuration初始化網絡下載會話
let session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
// 3:session建立downloadTask任務-resume啓動
let url = URL(string: "https://dldir1.qq.com/qqfile/QQforMac/QQ_V6.5.5.dmg")!
session.downloadTask(with: url).resume()
複製代碼
  • 接下來就是第4步,設置代理。依賴蘋果封裝的網絡處理API,發起鏈接 - 發送相關請求 - 回調代理響應 這裏只須要實現兩個回調就能夠了
//MARK: - session代理
extension ViewController:URLSessionDownloadDelegate{
//下載完成回調
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
        // 下載完成 - 開始沙盒遷移
        print("下載完成 - \(location)")
        let locationPath = location.path
        //拷貝到用戶目錄(文件名以時間戳命名)
        let documnets = NSHomeDirectory() + "/Documents/" + self.lgCurrentDataTurnString() + ".mp4"
        print("移動地址:\(documnets)")
        //建立文件管理器
        let fileManager = FileManager.default
        try! fileManager.moveItem(atPath: locationPath, toPath: documnets)
    }
    //下載進度回調
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
        print(" bytesWritten \(bytesWritten)\n totalBytesWritten \(totalBytesWritten)\n totalBytesExpectedToWrite \(totalBytesExpectedToWrite)")
        print("下載進度: \(Double(totalBytesWritten)/Double(totalBytesExpectedToWrite))\n")
    }
}
複製代碼
  • 接着下須要處理第5步中的backgroundSessionCompletionHandler回調。定義一個全局變量用於保存後臺下載的completionHandler
class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    //用於保存後臺下載的completionHandler
    var backgroundSessionCompletionHandler: (() -> Void)?
    func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
        self.backgroundSessionCompletionHandler = completionHandler
    }
}
複製代碼

注意:咱們經過handleEventsForBackgroundURLSession保存相應的回調,這也是很是必要的!告訴系統後臺下載回來及時刷新屏幕網絡

  • 最後第6步:在urlSessionDidFinishEvents的代理實現調用。代碼以下:
func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
    print("後臺任務下載回來")
    //由於涉及到UI刷新,須要確保在主線程中進行
    //若是不執行下面代碼,會致使剛進入前臺時頁面卡頓,影響用戶體驗,同時還會打印警告信息。
    DispatchQueue.main.async {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate, let backgroundHandle = appDelegate.backgroundSessionCompletionHandler else { return }
        backgroundHandle()
    }
}
複製代碼

注意:若是不實現第6步這個代理裏面的回調函數的執行,系統會打印警告信息:`Warning: Application delegate received call to - application:handleEventsForBackgroundURLSession:completionHandler: but the completion handler was never called. 雖然這樣仍是能夠實現後臺下載,可是會致使總在IOS系統總在後臺刷新,致使性能浪費,出現頁面卡頓,影響用戶體驗。session

  • 完成如上6個步驟就能夠實現後臺下載功能.保存handleEventsForBackgroundURLSession方法的completionHandler回調,這是很是重要的。告訴系統後臺下載回來及時刷新屏幕.
  • 在切到後臺以後,URLSessionDownloadDelegate 的代理方法不會再收到 Task 相關的消息。當全部 Task 全都完成後,系統纔會調用 AppDelegate 的application:handleEventsForBackgroundURLSession:completionHandler:回調。

Alamofire後臺下載

在講解Alamofire後臺下載前,有必要先熟悉一下Alamofire下載須要使用的幾個關鍵類。app

SessionManager

參考:大神Cooci博客:juejin.cn/post/684490…框架

相關文章
相關標籤/搜索