一個非常簡單易用且功能豐富的純Swift下載框架-Tiercel

Danie1s發表於2018-03-17

專案地址:github.com/Danie1s/Tie…

Tiercel

Tiercel是一個非常簡單易用且功能豐富的純Swift下載框架。最大的特點就是擁有強大的任務管理功能和可以直接獲取常見的下載資訊,並且只要加上一些簡單的UI,就可以實現一個下載類APP的大部分功能。

Features:

  • [x] 支援大檔案下載
  • [x] 支援離線斷點續傳,APP關閉後依然可以恢復所有下載任務
  • [x] 每個下載任務都可以單獨管理操作
  • [x] 每個下載任務和manager都有進度回撥、成功回撥和失敗回撥
  • [x] 棄用單例模式,APP裡面可以有多個manager,可以根據需要區分不同的下載模組
  • [x] 內建了常見的下載資訊,並且可以選擇是否持久化下載任務資訊
  • [x] 支援後臺下載
  • [x] 鏈式語法呼叫
  • [x] 可以控制下載的最大併發數
  • [x] 執行緒安全

Requirements

  • iOS 8.0+
  • Xcode 9.0+
  • Swift 4.0+​

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 Example.xcodeproj from the Example directory.

一個非常簡單易用且功能豐富的純Swift下載框架-Tiercel 一個非常簡單易用且功能豐富的純Swift下載框架-Tiercel

Usage

最簡單的用法

只需要簡單的幾行程式碼即可開啟下載

let URLString = "http://120.25.226.186:32812/resources/videos/minion_01.mp4"
let downloadManager = TRManager()
// 建立下載任務並且開啟下載
downloadManager.download(URLString)
複製程式碼

當然也可以對下載任務設定回撥

downloadManager.download(URLString, fileName: "小黃人1.mp4", progressHandler: { (task) in
    let progress = task.progress.fractionCompleted                                                                        
    print("下載中, 進度:\(progress)")
}, successHandler: { (task) in
    print("下載完成")
}) { (task) in
    print("下載失敗")
}
複製程式碼

下載任務的管理和操作

// 建立下載任務並且開啟下載,同時返回可選型別的TRDownloadTask物件,如果URLString無效,則返回nil
let task = downloadManager.download(URLString)
// 根據URLString查詢下載任務,返回可選型別的FCTask物件,如果不存在,則返回nil
let task = downloadManager.fetchTask(URLString)

// 開始下載
// 如果設定了downloadManager.isStartDownloadImmediately = false,需要手動開啟下載
// 如果呼叫suspend暫停了下載,可以呼叫這個方法繼續下載
downloadManager.start(URLString)

// 暫停下載
downloadManager.suspend(URLString)

// 取消下載,沒有下載完成的任務會被移除,但保留沒有下載完成的快取檔案
downloadManager.cancel(URLString)

// 移除下載,已經完成的任務也會被移除,沒有下載完成的快取檔案會被刪除,已經下載完成的檔案可以選擇是否保留
downloadManager.remove(URLString, completely: false)
複製程式碼

TRManager

TRManager是下載任務的管理者,管理所有下載任務,要使用Tiercel進行下載,必須要先建立TRManager物件。Tiercel沒有設計成單例模式,因為一個APP可能會有多個不同的下載模組,開發者可以根據需求建立多個TRManager物件來進行下載。

///  初始化方法
///
/// - Parameters:
///   - name: 設定TRManager物件的名字,區分不同的下載模組,每個模組中下載相關的檔案會儲存到對應的沙盒目錄
///   - MaximumRunning: 下載的最大併發數
///   - isStoreInfo: 是否把下載任務的相關資訊持久化到沙盒,如果是,則初始化完成後自動恢復上次的任務
public init(_ name: String? = nil, MaximumRunning: Int? = nil, isStoreInfo: Bool = false) {
    // 實現的程式碼... 
}
複製程式碼

開啟下載任務,並且對其進行管理。Tiercel的設計理念是一個URLString對應一個下載任務,所有操作都必須通過TRManager物件進行,URLString作為下載任務的唯一標識。

let URLString = "http://120.25.226.186:32812/resources/videos/minion_01.mp4"
let downloadManager = TRManager()

// 如果URLString無效,則返回nil
let task = downloadManager.download(URLString, fileName: "小黃人1.mp4", progressHandler: {  (task) in
    let progress = task.progress.fractionCompleted                                                                        
    print("下載中, 進度:\(progress)")
}, successHandler: { (task) in
    print("下載完成")
}) { (task) in
    print("下載失敗")
}

// 批量開啟下載任務,返回有效URLString對應的任務陣列,URLStrings需要跟fileNames一一對應
let tasks = downloadManager.multiDownload(URLStrings, fileNames: fileNames)


// 根據URLString查詢下載任務,返回可選型別的FCTask物件
// let task = downloadManager.fetchTask(URLString)

// 開始下載
// 如果設定了downloadManager.isStartDownloadImmediately = false,需要手動開啟下載
// 如果呼叫suspend暫停了下載,可以呼叫這個方法繼續下載
downloadManager.start(URLString)

// 暫停下載
downloadManager.suspend(URLString)

// 取消下載,沒有下載完成的任務會被移除,但保留沒有下載完成的快取檔案
downloadManager.cancel(URLString)

// 移除下載,已經完成的任務也會被移除,沒有下載完成的快取檔案會被刪除,已經下載完成的檔案可以選擇是否保留
downloadManager.remove(URLString, completely: false)
複製程式碼

TRManager也提供了對所有任務同時操作的API

downloadManager.totalStart()
downloadManager.totalSuspend()
downloadManager.totalCancel()
downloadManager.totalRemove(completely: false)
複製程式碼

TRManager作為所有下載任務的管理者,也可以設定回撥

// 回撥閉包的引數都是TRManager物件,因為開發者可以通過TRManager物件得到任何相關的資訊,把靈活度最大化
// 回撥閉包都是在主執行緒執行
// progress 閉包:只要有一個任務正在下載,就會觸發
// success 閉包:有兩種情況會觸發:
//    1. 所有任務都下載成功(取消和移除的任務會被移除然後銷燬,不再被manager管理) ,這時候manager.status == .completed
//    2. 任何一個任務的狀態都不是成功或者失敗,且沒有等待執行的任務,也沒有正在執行的任務,這時候manager.status == .suspend
// failure 閉包:有三種情況會觸發:
//    1. 每個任務的狀態是成功或者失敗,且有一個是失敗的,這時候manager.status == .failed
//    2. 呼叫全部取消的方法,或者剩下一個任務的時候把這個任務取消,這時候manager.status == .cancel
//    3. 呼叫全部移除的方法,或者剩下一個任務的時候把這個任務移除,這時候manager.status == .remove
downloadManager.progress { (manager) in
    let progress = manager.progress.fractionCompleted
    print("downloadManager執行中, 總進度:\(progress)")
    }.success { (manager) in
        if manager.status == .suspend {
            print("manager暫停了")
        } else if manager.status == .completed {
            print("所有下載任務都下載成功")
        }
    }.failure { (manager) in
        if manager.status == .failed {
            print("存在下載失敗的任務")
        } else if manager.status == .cancel {
            print("manager取消了")
        } else if manager.status == .remove {
            print("manager移除了")
        }
}
複製程式碼

Tiercel的銷燬

// 由於Tiercel是使用URLSession實現的,session需要手動銷燬,所以當不再需要使用Tiercel也需要手動銷燬
// 一般在控制器中新增以下程式碼
deinit {
    downloadManager.invalidate()
}
複製程式碼

TRManager的主要屬性

// 設定內建日誌列印等級,如果為none則不列印
public static var logLevel: TRLogLevel = .high
// 設定是否建立任務後馬上下載,預設為是
public var isStartDownloadImmediately = true
// TRManager的狀態
public var status: FCStatus = .waiting
// TRManager的快取管理物件
public var cache: TRCache
// TRManager的進度
public var progress: Progress
// 設定請求超時時間
public var timeoutIntervalForRequest = 30.0
// 所有下載中的任務加起來的總速度
public private(set) var speed: Int64 = 0
// 所有下載中的任務需要的剩餘時間
public private(set) var timeRemaining: Int64 = 0

// manager管理的下載任務,取消和移除的任務會被銷燬,不會在陣列裡,但操作是非同步的,馬上獲取的tasks可能不正確
public var tasks: [FCTask] = []
複製程式碼

TRCache

TRCache是Tiercel中負責管理快取下載任務資訊和下載檔案的類。同樣地,TRCache沒有設計成單例模式,TRCache物件一般作為TRManager物件的屬性來使用,如果需要跨控制器使用,那麼只需要建立跟TRManager物件同樣名字的TRCache物件即可操作對應模組的快取資訊和檔案。

/// 初始化方法
///
/// - Parameters:
///   - name: 設定TRCache物件的名字,一般由TRManager物件建立時傳遞
///   - isStoreInfo: 是否把下載任務的相關資訊持久化到沙盒,一般由TRManager物件建立時傳遞
public init(_ name: String, isStoreInfo: Bool = false) {
    // 實現的程式碼...
}
複製程式碼

主要屬性

// 下載模組的目錄路徑
public let downloadPath: String

// 沒有完成的下載檔案快取的目錄路徑
public let downloadTmpPath: String

// 下載完成的檔案的目錄路徑
public let downloadFilePath: String
複製程式碼

主要API分成幾大類:

  • 檢查沙盒是否存在檔案

  • 移除跟下載任務相關的檔案

  • 儲存跟下載任務相關的檔案

  • 讀取下載任務相關的檔案,獲得下載任務相關的資訊

TRDownloadTask

TRDownloadTask是Tiercel中的下載任務類,繼承自FCTask。**Tiercel的設計理念是一個URLString對應一個下載任務,所有操作都必須通過TRManager物件進行,URLString作為下載任務的唯一標識。**所以TRDownloadTask物件都是由TRManager物件建立,單獨建立沒有意義。

主要屬性

// 儲存到沙盒的下載檔案的檔名,如果在下載的時候沒有設定,則預設使用url的最後一部分
public internal(set) var fileName: String
// 下載任務對應的URLString
public var URLString: String
// 下載任務的狀態
public var status: FCStatus = .waiting
// 下載任務的進度
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
複製程式碼

下載任務的回撥,可以在使用TRManager物件開啟下載的時候設定,也可以在獲得TRDownloadTask物件後進行設定

let task = downloadManager.fetchTask(URLString)

// 回撥閉包的引數都是TRDownloadTask物件,因為開發者可以通過TRDownloadTask物件得到任何相關的資訊,把靈活度最大化
// 回撥閉包都是在主執行緒執行
// progress 閉包:如果任務正在下載,就會觸發
// success 閉包:任務已經下載過了,或者任務下載完成時,會觸發
// failure 閉包:有三種情況會觸發:
//    1. 任務下載失敗,這時候task.status == .failed
//    2. 取消任務,這時候task.status == .cancel
//    3. 移除任務,或者剩下一個任務的時候把這個任務移除,這時候manager.status == .remove
task.progress { (task) in
     let progress = task.progress.fractionCompleted
     printLog("下載中, 進度:\(progress)")
    }
    .success({ (task) in
        printLog("下載完成")
    })
    .failure({  (task) in
        if task.status == .failed {
            print("下載失敗")
        } else if task.status == .cancel {
            print("取消任務")
        } else if task.status == .remove {
            print("移除任務")
        }
    })
複製程式碼

對下載任務操作,必須通過TRManager物件進行,不能用TRDownloadTask物件直接操作

  • 開啟
  • 暫停
  • 取消,會從TRManager物件中的tasks中移除,但保留沒有下載完成的快取檔案
  • 移除,已經完成的任務也會被移除,沒有下載完成的快取檔案會被刪除,已經下載完成的檔案可以選擇是否保留

注意:取消和移除的任務會被銷燬,會從TRManager物件的tasks中移除,但操作是非同步的,馬上獲取的tasks可能不正確,在回撥閉包裡面獲取的tasks才能保證正確

後臺下載

如果需要開啟後臺下載,只需要在專案的info.plist中新增Required background modes -> App downloads content from the network

License

Tiercel is available under the MIT license. See the LICENSE file for more info.

相關文章