Cribug(名称取自魁拔,支持国漫!)是一个简单易用且功能丰富的纯 Swift 下载框架。其最大的特点是强大的任务管理功能,可以直接获取下载速度等常见的下载信息。只要加入一些简单的 UI,就可以实现下载类 APP 的大部分功能。
功能
- 支持大文件下载
- 支持离线断点续传,APP 关闭后依然可以恢复所有下载任务
- 支持多任务下载,每个下载任务都可以单独管理操作
- manager 和每个下载任务都有进度回调、成功回调和失败回调
- 弃用单例模式,APP 里面可以有多个 manager,可以根据需要区分不同的下载模块
- 内置了下载速度等常见的下载信息,并且可以选择是否持久化下载任务信息
- 链式语法调用
- 支持控制下载任务的最大并发数
- 线程安全
要求
- iOS 8.0+
- Xcode 9.0+
- Swift 4.0+
安装
CocoaPods
CocoaPods 是 Cocoa 项目的依赖管理器。您可以使用以下命令安装它
$ gem install cocoapods
要构建 Cribug 需要 CocoaPods 1.1+。
使用 CocoaPods 将 Cribug 集成到您的 Xcode 项目中,请在您的 Podfile
中指定它
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!
target '<Your Target Name>' do
pod 'Cribug'
end
然后,运行以下命令
$ pod install
手动
如果你不希望使用上述任何依赖管理器,你可以手动将Cribug集成到项目中。
示例
要运行示例项目,请克隆仓库,并运行 Cribug.xcodeproj
。
用法
最简单的用法
只需要简单的几行代码即可开始下载。
let URLString = "http://120.25.226.186:32812/resources/videos/minion_01.mp4"
let downloadManager = MCManager()
// 创建下载任务并且开启下载
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("下载失败")
}
下载任务的管理和操作。
// 创建下载任务并且开启下载,同时返回可选类型的MCDownloadTask实例,如果URLString无效,则返回nil
let task = downloadManager.download(URLString)
// 根据URLString查找下载任务,返回可选类型的MCTask实例,如果不存在,则返回nil
let task = downloadManager.fetchTask(URLString)
// 开始下载
// 如果设置了downloadManager.isStartDownloadImmediately = false,需要手动开启下载
// 如果调用suspend暂停了下载,可以调用这个方法继续下载
downloadManager.start(URLString)
// 暂停下载
downloadManager.suspend(URLString)
// 取消下载,没有下载完成的任务会被移除,但保留没有下载完成的缓存文件
downloadManager.cancel(URLString)
// 移除下载,已经完成的任务也会被移除,没有下载完成的缓存文件会被删除,已经下载完成的文件可以选择是否保留
downloadManager.remove(URLString, completely: false)
MCManager
MCManager是Cribug中下载任务的管理者,管理所有下载任务。如果要使用Cribug进行下载,必须先创建MCManager实例。Cribug没有设计为单例模式,因为一个应用中可能会有多个不同的下载模块,开发者可以根据需求创建多个MCManager实例来进行下载。
/// 初始化方法
///
/// - Parameters:
/// - name: 设置MCManager实例的名字,区分不同的下载模块,每个模块中下载相关的文件会保存到对应的沙盒目录
/// - MaximumRunning: 下载的最大并发数
/// - isStoreInfo: 是否把下载任务的相关信息持久化到沙盒,如果是,则初始化完成后自动恢复上次的任务
public init(_ name: String? = nil, MaximumRunning: Int? = nil, isStoreInfo: Bool = false) {
// 实现的代码...
}
启动下载任务,并对其进行管理。Cribug的设计理念是每个URLString对应一个下载任务,所有操作都必须通过MCManager实例进行,URLString作为下载任务的唯一标识。
let URLString = "http://120.25.226.186:32812/resources/videos/minion_01.mp4"
let downloadManager = MCManager()
// 如果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查找下载任务,返回可选类型的MCTask实例
// let task = downloadManager.fetchTask(URLString)
// 开始下载
// 如果设置了downloadManager.isStartDownloadImmediately = false,需要手动开启下载
// 如果调用suspend暂停了下载,可以调用这个方法继续下载
downloadManager.start(URLString)
// 暂停下载
downloadManager.suspend(URLString)
// 取消下载,没有下载完成的任务会被移除,但保留没有下载完成的缓存文件
downloadManager.cancel(URLString)
// 移除下载,已经完成的任务也会被移除,没有下载完成的缓存文件会被删除,已经下载完成的文件可以选择是否保留
downloadManager.remove(URLString, completely: false)
MCManager还提供了对任务进行批量操作的API。
downloadManager.totalStart()
downloadManager.totalSuspend()
downloadManager.totalCancel()
downloadManager.totalRemove(completely: false)
MCManager也可以设置回调。
// 回调闭包的参数都是MCManager实例,因为开发者可以通过MCManager实例得到任何相关的信息,把灵活度最大化
// 回调闭包都是在主线程运行
// 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移除了")
}
}
Cribug的销毁
// 由于Cribug是使用URLSession实现的,session需要手动销毁,所以当不再需要使用Cribug也需要手动销毁
// 一般在控制器中添加以下代码
deinit {
downloadManager.invalidate()
}
MCManager的主要属性
// 设置内置日志打印等级,如果为none则不打印
public static var logLevel: MCLogLevel = .high
// 默认对networkActivityIndicator进行管理,可以取消
public static var isControlNetworkActivityIndicator = true
// 设置是否创建任务后马上下载,默认为是
public var isStartDownloadImmediately = true
// MCManager的状态
public var status: MCStatus = .waiting
// MCManager的缓存管理实例
public var cache: MCCache
// MCManager的进度
public var progress: Progress
// 设置请求超时时间
public var timeoutIntervalForRequest = 30.0
// 所有下载中的任务加起来的总速度
public private(set) var speed: Int64 = 0
// 所有下载中的任务需要的剩余时间
public private(set) var timeRemaining: Int64 = 0
// manager管理的下载任务,取消和移除的任务会被销毁,但操作是异步的,在回调闭包里面获取才能保证正确
public var tasks: [MCTask] = []
MCCache
MCCache是Cribug中负责管理缓存下载任务信息和下载文件的类。同样地,MCCache没有设计为单例模式,MCCache实例通常作为MCManager实例的属性来使用,如果需要跨控制器使用,那么只需要创建与MCManager实例同名的MCCache实例即可操作对应模块的缓存信息和文件。
/// 初始化方法
///
/// - Parameters:
/// - name: 设置MCCache实例的名字,一般由MCManager实例创建时传递
/// - isStoreInfo: 是否把下载任务的相关信息持久化到沙盒,一般由MCManager实例创建时传递
public init(_ name: String, isStoreInfo: Bool = false) {
// 实现的代码...
}
主要属性
// 下载模块的目录路径
public let downloadPath: String
// 没有完成的下载文件缓存的目录路径
public let downloadTmpPath: String
// 下载完成的文件的目录路径
public let downloadFilePath: String
主要的API分为几大类:
-
检查沙盒中是否存在文件
-
移除与下载任务相关的文件
-
保存与下载任务相关的文件
-
读取与下载任务相关的文件,获取下载任务相关信息
MCDownloadTask
MCDownloadTask是Cribug中的下载任务类,继承自MCTask。Cribug的设计理念是一个URLString对应一个下载任务,所有操作都必须通过MCManager实例进行,URLString作为下载任务的唯一标识。所以MCDownloadTask实例都是由MCManager实例创建,单独创建没有意义。
主要属性
// 保存到沙盒的下载文件的文件名,如果在下载的时候没有设置,则默认使用url的最后一部分
public internal(set) var fileName: String
// 下载任务对应的URLString
public var URLString: String
// 下载任务的状态
public var status: MCStatus = .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
下载任务的回调,可以在使用MCManager实例开启下载的时候设置,也可以在获得MCDownloadTask实例后进行设置
let task = downloadManager.fetchTask(URLString)
// 回调闭包的参数都是MCDownloadTask实例,因为开发者可以通过MCDownloadTask实例得到任何相关的信息,把灵活度最大化
// 回调闭包都是在主线程运行
// progress 闭包:如果任务正在下载,就会触发
// success 闭包:有两种情况会触发:
// 1. 任务已经下载过了,或者任务下载完成,这时候task.status == .completed
// 2. 暂停下载任务,这时候task.status == .suspend
// failure 闭包:有三种情况会触发:
// 1. 任务下载失败,这时候task.status == .failed
// 2. 取消任务,这时候task.status == .cancel
// 3. 移除任务,或者剩下一个任务的时候把这个任务移除,这时候manager.status == .remove
task.progress { (task) in
let progress = task.progress.fractionCompleted
print("下载中, 进度:\(progress)")
}
.success({ (task) in
if task.status == .suspend {
print("下载暂停")
} else if task.status == .completed {
print("下载完成")
}
})
.failure({ (task) in
if task.status == .failed {
print("下载失败")
} else if task.status == .cancel {
print("取消任务")
} else if task.status == .remove {
print("移除任务")
}
})
对下载任务操作,必须通过MCManager实例进行,不能用MCDownloadTask实例直接操作
- 开启
- 暂停
- 取消,会从MCManager实例中的tasks中移除,但保留没有下载完成的缓存文件
- 移除,已经完成的任务也会被移除,没有下载完成的缓存文件会被删除,已经下载完成的文件可以选择是否保留
注意:对下载中的任务进行暂停、取消和移除操作,结果是异步回调的,在回调闭包里面获取状态才能保证正确
后台下载
如果需要开启后台下载,只需要在项目的info.plist中添加Required background modes -> App downloads content from the network
目前正在寻找其它解决办法
授权
Cribug遵循MIT授权协议。更多信息请参阅LICENSE文件。