Tiercel 2!完美支援原生級別後臺下載
專案地址: github.com/Danie1s/Tie…
Tiercel是一個簡單易用且功能豐富的純Swift下載框架,支援原生級別後臺下載,擁有強大的任務管理功能,滿足下載類APP的大部分需求。
Tiercel 2:
Tiercel 2 是全新的版本,下載實現基於 URLSessionDownloadTask
,支援原生的後臺下載,功能更加強大,使用方式也有了一些改變,不相容舊版本,請注意新版的使用方法。如果想了解後臺下載的細節和注意事項,可以看這篇文章: iOS原生級別後臺下載詳解
舊版本下載實現基於 URLSessionDataTask
,不支援後臺下載,已經移至 dataTask
分支,原則上不再更新,如果不需要後臺下載功能,或者不想遷移到新版,可以直接下載 dataTask
分支的原始碼使用,也可以在 Podfile
裡使用以下方式安裝:
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! target '<Your Target Name>' do pod 'Tiercel', :git => 'https://github.com/Danie1s/Tiercel.git', :branch => 'dataTask' end 複製程式碼
Features:
- 原生級別的後臺下載
- 支援離線斷點續傳,無論crash還是手動Kill App都不會影響
- 精細的任務管理,每個下載任務都可以單獨管理操作和狀態回撥
- 支援多個下載模組,每個模組擁有一個管理者,每個模組互不影響
- 下載模組的管理者擁有總任務的狀態回撥
- 內建了下載速度、剩餘時間等常見的下載資訊
- 鏈式語法呼叫
- 支援控制下載任務的最大併發數
- 支援檔案校驗
- 執行緒安全
Requirements
- iOS 8.0+
- Xcode 10.0+
- Swift 4.2+
Installation
CocoaPods
CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:
$ gem install cocoapods 複製程式碼
CocoaPods 1.1+ is required to build Tiercel.
To integrate Tiercel into your Xcode project using CocoaPods, specify it in your Podfile
:
source 'https://github.com/CocoaPods/Specs.git' platform :ios, '8.0' use_frameworks! target '<Your Target Name>' do pod 'Tiercel' end 複製程式碼
Then, run the following command:
$ pod install 複製程式碼
Manually
If you prefer not to use any of the aforementioned dependency managers, you can integrate Tiercel into your project manually.
Example
To run the example project, clone the repo, and run Tiercel.xcodeproj
.


Usage
配置
Tiercel內建一個全域性的 TRManager.default
單例,因為支援原生後臺下載,所以需要在 AppDelegate
檔案裡配置
以下為內建的 default
單例配置方法,如果需要使用多個下載模組,或者需要自定義 TRManager
,可參照 Demo
// 在AppDelegate檔案裡 func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // 如果有使用內建全域性的default單例,必須在此方法內呼叫一次,否則不會在App啟動的時候初始化 // 在這裡進行初始化的配置,也可以在任何地方,隨時進行配置 TRManager.default.configuration.allowsCellularAccess = true return true } // 必須實現此方法,並且把identifier對應的completionHandler儲存起來 func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) { if TRManager.default.identifier == identifier { TRManager.default.completionHandler = completionHandler } } 複製程式碼
基本用法
一行程式碼開啟下載
// 建立下載任務並且開啟下載,同時返回可選型別的TRDownloadTask例項,如果URLString無效,則返回nil let task = TRManager.default.download("http://api.gfs100.cn/upload/20171219/201712191530562229.mp4") // 批量建立下載任務並且開啟下載,返回有效URLString對應的任務陣列,URLStrings需要跟fileNames一一對應 let tasks = TRManager.default.multiDownload(URLStrings) 複製程式碼
如果需要設定回撥
// 回撥閉包的引數是TRDownloadTask例項,可以得到所有相關的資訊 // 回撥閉包都是在主執行緒執行 // progress 閉包:如果任務正在下載,就會觸發 // success 閉包:任務已經下載過,或者下載完成,都會出發,這時候task.status == .succeeded // failure 閉包:只要task.status != .succeeded,就會觸發: //1. 暫停任務,這時候task.status == .suspended //2. 任務下載失敗,這時候task.status == .failed //3. 取消任務,這時候task.status == .canceled //4. 移除任務,這時候task.status == .removed let task = TRManager.default.download("http://api.gfs100.cn/upload/20171219/201712191530562229.mp4") task?.progress({ (task) in let progress = task.progress.fractionCompleted print("下載中, 進度:\(progress)") }).success({ (task) in print("下載完成") }).failure({ (task) in print("下載失敗") }) 複製程式碼
下載任務的管理和操作。 在Tiercel中,URLString是下載任務的唯一標識,如果需要對下載任務進行操作,則使用TRManager例項對URLString進行操作。
let URLString = "http://api.gfs100.cn/upload/20171219/201712191530562229.mp4" // 建立下載任務並且開啟下載,同時返回可選型別的TRDownloadTask例項,如果URLString無效,則返回nil let task = TRManager.default.download(URLString) // 根據URLString查詢下載任務,返回可選型別的TRTask例項,如果不存在,則返回nil let task = TRManager.default.fetchTask(URLString) // 開始下載 // 如果呼叫suspend暫停了下載,可以呼叫這個方法繼續下載 TRManager.default.start(URLString) // 暫停下載 TRManager.default.suspend(URLString) // 取消下載,沒有下載完成的任務會被移除,不保留快取,已經下載完成的不受影響 TRManager.default.cancel(URLString) // 移除下載,任何狀態的任務都會被移除,沒有下載完成的快取檔案會被刪除,可以選擇是否保留已經下載完成的檔案 TRManager.default.remove(URLString, completely: false) // 除了可以對單個任務進行操作,TRManager也提供了對所有任務同時操作的API TRManager.default.totalStart() TRManager.default.totalSuspend() TRManager.default.totalCancel() TRManager.default.totalRemove(completely: false) 複製程式碼
後臺下載
Tiercel 2 的下載實現基於 URLSessionDownloadTask
,支援原生的後臺下載,按照蘋果官方文件的要求,TRManager例項必須在App啟動的時候建立,並且在 AppDelegate
檔案裡實現以下方法
// 必須實現此方法,並且把identifier對應的completionHandler儲存起來 func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) { if TRManager.default.identifier == identifier { TRManager.default.completionHandler = completionHandler } } 複製程式碼
只要使用Tiercel 開啟了下載任務:
- 手動Kill App,任務會暫時,重啟App後可以恢復進度,繼續下載
- 只要不是手動Kill App,任務會一直在下載
- 把App退回後臺,任務會一直在下載
- 無論在前臺還是後臺,如果App崩潰或者被系統關閉,任務還是會一直在下載
- 重啟手機,任務會一直在下載
如果想了解後臺下載的細節和注意事項,可以看這篇文章: iOS原生級別後臺下載詳解
檔案校驗
Tiercel提供了檔案校驗功能,可以根據需要新增,校驗結果在回撥的 task.validation
裡
// 回撥閉包在主執行緒執行 let task = TRManager.default.download("http://dldir1.qq.com/qqfile/QQforMac/QQ_V4.2.4.dmg") task?.validateFile(verificationCode: "9e2a3650530b563da297c9246acaad5c", verificationType: .md5, validateHandler: { (task) in if task.validation == .correct { // 檔案正確 } else { // 檔案錯誤 } }) 複製程式碼
TRChecksumHelper是檔案校驗的工具類,可以直接使用它對已經存在的檔案進行校驗
/// 對檔案進行校驗,是在子執行緒進行的 /// /// - Parameters: ///- filePath: 檔案路徑 ///- verificationCode: 檔案的Hash值 ///- verificationType: Hash型別 ///- completion: 完成回撥 public class func validateFile(_ filePath: String, verificationCode: String, verificationType: TRVerificationType, completion: @escaping (Bool) -> ()) { } 複製程式碼
TRManager
TRManager是下載任務的管理者,管理當前模組所有下載任務,內建一個全域性的 default
單例,如果需要多個下載模組,或者需要自定義TRManager,可以手動建立TRManager例項。
:warning::warning::warning:按照蘋果官方文件的要求,TRManager例項必須在App啟動的時候建立,即TRManager的生命週期跟App幾乎一致,為方便使用,最好是作為 AppDelegate
的屬性,或者是全域性變數,具體請參照 Demo
。
///初始化方法 /// /// - Parameters: ///- identifier: 設定TRManager例項的標識,區分不同的下載模組,同時為urlSession的標識,原生級別的後臺下載必須要有唯一標識 public init(_ identifier: String) { // 實現的程式碼... } 複製程式碼
TRManager作為所有下載任務的管理者,也可以設定回撥
// 回撥閉包的引數是TRManager例項,可以得到所有相關的資訊 // 回撥閉包都是在主執行緒執行 // progress 閉包:只要有一個任務正在下載,就會觸發 // success 閉包:只有一種情況會觸發: //所有任務都下載成功(取消和移除的任務會被移除然後銷燬,不再被manager管理) ,這時候manager.status == .succeeded // failure 閉包:只要manager.status != .succeeded,就會觸發: //1. 呼叫全部暫停的方法,或者沒有等待執行的任務,也沒有正在執行的任務,這時候manager.status == .suspended //2. 所有任務都結束,但有一個或者多個是失敗的,這時候manager.status == .failed //3. 呼叫全部取消的方法,或者剩下一個任務的時候把這個任務取消,這時候manager.status == .canceled //4. 呼叫全部移除的方法,或者剩下一個任務的時候把這個任務移除,這時候manager.status == .removed TRManager.default.progress { (manager) in let progress = manager.progress.fractionCompleted print("downloadManager執行中, 總進度:\(progress)") }.success { (manager) in print("所有下載任務都成功了") }.failure { (manager) in if manager.status == .suspended { print("所有下載任務都暫停了") } else if manager.status == .failed { print("存在下載失敗的任務") } else if manager.status == .canceled { print("所有下載任務都取消了") } else if manager.status == .removed { print("所有下載任務都移除了") } } 複製程式碼
TRManager的主要屬性
// 內建的全域性單例 public static let `default` = TRManager("default") // 設定內建日誌列印等級,如果為none則不列印 public static var logLevel: TRLogLevel = .detailed // 是否需要對networkActivityIndicator進行管理 public static var isControlNetworkActivityIndicator = true // TRManager的狀態 public var status: TRStatus = .waiting // TRManager的快取管理例項 public var cache: TRCache // TRManager的標識,區分不同的下載模組 public let identifier: String // TRManager的進度 public var progress: Progress // TRManager的配置,可以設定請求超時時間,最大併發數,是否允許蜂窩網路下載 public var configuration = TRConfiguration() // 所有下載中的任務加起來的總速度 public private(set) var speed: Int64 = 0 // 所有下載中的任務需要的剩餘時間 public private(set) var timeRemaining: Int64 = 0 // manager管理的下載任務,取消和移除的任務會被銷燬,但操作是非同步的,在回撥閉包裡面獲取才能保證正確 public var tasks: [TRTask] = [] 複製程式碼
TRConfiguration
TRConfiguration是Tiercel中配置TRManager的結構體,可配置屬性如下:
// 請求超時時間 public var timeoutIntervalForRequest = 30.0 // 最大併發數 public var maxConcurrentTasksLimit = Int.max // 是否允許蜂窩網路下載 public var allowsCellularAccess = false 複製程式碼
更改TRManager的配置
// 無論是否有下載任務正在執行,都可以在任何地方,隨時配置 // 如果只是更改某一項,可以直接對TRManager屬性設定 TRManager.default.configuration.allowsCellularAccess = true // 如果是需要更改多項,最好是重新建立TRConfiguration let configuration = TRConfiguration() configuration.allowsCellularAccess = true configuration.maxConcurrentTasksLimit = 2 configuration.timeoutIntervalForRequest = 60 TRManager.default.configuration = configuration 複製程式碼
TRDownloadTask
TRDownloadTask是Tiercel中的下載任務類,繼承自TRTask。**在Tiercel中,URLString是下載任務的唯一標識,URLString代表著任務,如果需要對下載任務進行操作,則使用TRManager例項對URLString進行操作。**所以TRDownloadTask例項都是由TRManager例項建立,單獨建立沒有意義。
主要屬性
// 儲存到沙盒的下載檔案的檔名,如果在下載的時候沒有設定,則預設為url的md5加上副檔名 public internal(set) var fileName: String // 下載任務對應的URLString public let URLString: String // 下載任務的狀態 public var status: TRStatus // 下載檔案的校驗狀態 public var validation: TRValidation // 下載任務的進度 public var progress: Progress = Progress() // 下載任務的開始日期 public var startDate: TimeInterval = 0 // 下載任務的結束日期 public var endDate: TimeInterval = Date().timeIntervalSince1970 // 下載任務的速度 public var speed: Int64 = 0 // 下載任務的剩餘時間 public var timeRemaining: Int64 = 0 // 下載檔案路徑 public var filePath: String // 下載檔案的副檔名 public var pathExtension: String? 複製程式碼
對下載任務操作,必須通過TRManager例項進行,不能用TRDownloadTask例項直接操作
- 開啟
- 暫停
- 取消,沒有完成的任務從TRManager例項中的tasks中移除,不保留快取,已經下載完成的任務不受影響
- 移除,已經完成的任務也會被移除,沒有下載完成的快取檔案會被刪除,已經下載完成的檔案可以選擇是否保留
注意:對下載中的任務進行暫停、取消和移除操作,結果是非同步回撥的,在回撥閉包裡面獲取狀態才能保證正確
TRCache
TRCache是Tiercel中負責管理快取下載任務資訊和下載檔案的類。TRCache例項一般作為TRManager例項的屬性來使用,同樣地,Tiercel內建一個全域性的 TRCache.default
單例,對應 TRManager.default
。
/// 初始化方法 /// /// - Parameters: ///- name: 不同的name,代表不同的下載模組,對應的檔案放在不同的地方,對應TRManager建立時傳入的identifier public init(_ name: String) { // 實現的程式碼... } 複製程式碼
主要屬性
// 下載模組的目錄路徑 public let downloadPath: String // 沒有完成的下載檔案快取的目錄路徑 public let downloadTmpPath: String // 下載完成的檔案的目錄路徑 public let downloadFilePath: String 複製程式碼
主要API分成幾大類:
- 檢查沙盒是否存在檔案
- 移除跟下載任務相關的檔案
- 儲存跟下載任務相關的檔案
- 讀取下載任務相關的檔案,獲得下載任務相關的資訊
License
Tiercel is available under the MIT license. See the LICENSE file for more info.