Alamofire 學習(二)-URLSession 知識準備

1、簡介

iOS7 開始,蘋果推出了 URLSession ,在 OC 中叫 NSURLSession,取代了 URLConnection。因爲 Alamofire 底層也是封裝的 URLSession,因此咱們先來了解一下原生的 URLSession,再來學習 Alamofire 會更加透徹。若是朋友們已經對 URLSession 掌握的很好了,那麼能夠跳過此篇。swift

2、URLSession 請求

一、請求的基本流程

建立 configurations ➡️ 建立 session ➡️ 建立 task ➡️ resume() 開始請求➡️ 監聽回調api

URLSession.shared.dataTask(with: url) { (data, response, error) in
    if error == nil {
        print("請求成功\(String(describing: response))" )
    }
}.resume()
複製代碼

上面是 URLSession 的一個最基本的請求格式,其中 URLSession.shared 爲咱們提供了一個單例 session 對象,它爲建立任務提供了默認配置。 其中省略了configurations 的設置,其實上面的代碼也能夠詳細展開寫成下面這樣:服務器

let configure = URLSessionConfiguration.default
let session = URLSession.init(configuration: configure)
session.dataTask(with: url) { (data, response, error) in
    if error == nil {
        print("請求成功\(String(describing: response))" )
    }
}.resume()
複製代碼

URLSession 能夠經過 URLSessionConfiguration 建立 URLSession 實例。爲何第一部分代碼是能夠省略configure 的呢?cookie

URLSessionConfiguration:

緣由在於 configure 有三種類型:網絡

  • .default 是默認的值,這和 URLSession.shared 建立的 session 是同樣的,可是比起這個單例,它能夠進行更多的擴展配置。
  • .ephemeral ephemeralURLSession.shared 很類似,區別是 不會寫入 caches, cookiescredentials(證書)到磁盤。
  • .background 後臺 session,能夠在程序切到後臺、崩潰或未運行時進行上傳和下載。

URLSessionTask:

URLSessionTask 是一個表示任務對象的抽象類,一個會話(session)建立一個任務(task),這裏任務是指獲取數據、下載或上傳文件。 task 任務有四種類型:session

  • URLSessionDataTask:處理從HTTP get請求中從服務器獲取數據到內存中。
  • URLSessionUploadTask:上傳硬盤中的文件到服務器,通常是HTTP POST 或 PUT方式
  • URLSessionDownloadTask:從遠程服務器下載文件到臨時文件位置。
  • NSURLSessionStreamTask:基於流的URL會話任務,提供了一個經過 NSURLSession 建立的 TCP/IP 鏈接接口。

任務操做

注意:咱們的網絡任務默認是掛起狀態的(suspend),在獲取到 dataTask 之後須要使用 resume() 函數來恢復或者開始請求。app

  • resume():啓動任務
  • suspend():暫停任務
  • cancel():取消任務

二、後臺下載

自從有了 URLSessioniOS 才真正實現了後臺下載。下面是一個簡單的後臺下載的實現。async

一、初始化一個 background 的模式的 configuration

let configuration = URLSessionConfiguration.background(withIdentifier: self.createID())
複製代碼

二、經過 configuration 初始化網絡下載會話,設置相關代理,回調數據信號響應。

let session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
複製代碼

三、session 建立 downloadTask 任務- resume 啓動

session.downloadTask(with: url).resume()
複製代碼

四、發起鏈接 - 發送相關請求 - 回調代理響應

  • 下載進度 的代理回調 urlSession(_ session: downloadTask:didWriteData bytesWritten: totalBytesWritten: totalBytesExpectedToWrite: ) 來監聽下載進度:
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")
}
複製代碼

因爲 http 的分片傳輸,因此下載進度是隔一段時間回調一次的。ide

  • 下載完成 的代理回調 didFinishDownloadingTo,實現下載完成轉移臨時文件裏的數據到相應沙盒保存
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)
}
複製代碼

五、開啓後臺下載權限

除了這些,想要實現後臺下載還必須在 AppDelegate 中實現 handleEventsForBackgroundURLSession,開啓後臺下載權限:函數

class AppDelegate: UIResponder, UIApplicationDelegate {
    var window: UIWindow?
    //用於保存後臺下載的completionHandler
    var backgroundSessionCompletionHandler: (() -> Void)?
    func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
        self.backgroundSessionCompletionHandler = completionHandler
    }
}
複製代碼

六、在 urlSessionDidFinishEvents 中回調系統回調

還須要在主線程中回調系統回調,告訴系統及時更新屏幕

func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
    print("後臺任務下載回來")
    DispatchQueue.main.async {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate, let backgroundHandle = appDelegate.backgroundSessionCompletionHandler else { return }
        backgroundHandle()
    }
}
複製代碼

⚠️ 若是不實現這個代理裏面的回調函數,依然能夠實現後臺下載,但會出現卡頓的問題,控制檯也會出現警告。

Warning: Application delegate received call to - application:handleEventsForBackgroundURLSession:completionHandler: but the completion handler was never called.

URLSession 的基礎知識就先複習到這,下一篇就來正式學習一下 Alamofire

以上的總結參考了並部分摘抄瞭如下文章,很是感謝如下做者的分享!:

一、思緒_HY的《URLSession基本使用》

二、Cooci的《Alamofire-URLSession必備技能》

轉載請備註原文出處,不得用於商業傳播——凡幾多

相關文章
相關標籤/搜索