Reed
Reed is a downloader framework for Swift. It is many fetures, stability,fast, ow coupling, easily extended. It use ActiveSQLite to persist datas。
Features
- Multi download tasks
- Resume at break-point
- Max concurrent count
- Validate md5 file
- Check full space
- Thread safe
- Multi scope
- Log with CocoaLumberjack
- Background download
- OperationQueue
Demo
Design
- Core Downloader -> Pure Downloader
Core Downloader only exist memory, it not use database. Can use it download without Reed layer.
- Reed Download Manager -> Download Manager
It save download model in database, deal with download status changes, handle errors, post notifications.
Major Words
1 Model of download info
This is a simple version of model:
class ReedInfo {
var key:String = "" //Identifier
var url:String = ""
var md5:String?
var totalBytes:NSNumber = 0
var writedBytes:NSNumber = 0
var destFilePath = ""
var cacheFilePath = ""
var context = ""
var downloadListKey = ""
var downloadStatus:ReedDownloadStatus = .waiting
var downloadFailReason:ReedDownloadFailReason?
}
2 Status of download
public enum ReedDownloadStatus: String {
case waiting
case downloading
case pause
case completed
case faild
}
3 Reason of download failed
public enum ReedDownloadFailReason:String{
case unknown
case timeout
case noNetwork
case fullSpace
case md5Verification
}
Usage
Start download
1 Direct download
/// key: Identifier
/// url:
/// destinationFilePath:eg:”Documents/xxxx/filename.pdf“
/// downloadListKey : Default value is nil. can exist many than one downloadlist
/// md5: Value of md5. Default value is nil.
/// isReplace: Replace the old download destination file and cache file. Default value is false
Reed.shared.start(key:"key", url:"url", destinationFilePath:"Documents/filename.pdf",downloadListKey:"PDF_DOWNLOAD_LIST",md5:nil,isReplace:false)
2 Add task to download list at first, and then start it.
Reed.shared.addToStartList(key:"key", url:"url", destinationFilePath:"Documents/filename.xxx")
Reed.shared.start(key: "key")
3 Add task to download list at first, and then check to start(Recommend)
Reed.shared.addToStartList(key:"key", url:"url", destinationFilePath:"Documents/filename.xxx")
Reed.shared.checkToStart()
Introduce checkToStart()
Define:
checkToStart(downloadListKey:String? == nil)
Description:
check free space on device;
check max concurrent download count in the downloadlist;
start download task whoes is waiting status, and order by added date and ;
Use Case:
1,Network become available. opposite shutdown.
2.User login. opposite shutdown.
3.App launch if need.
4.Reed call by its self when a download task change its status (complete,pause,failed,delete). The downloading count sub 1, may start other waiting task.
Scope
First | Second | Third |
context1 | DownloadListKey1 | key1 |
key2 | ||
key3 | ||
DownloadListKey2 | key4 | |
key5 | ||
key6 | ||
key7 |
1 context
context is first level scope
The value of ReedInfo.context come from the value of Reed.shared.context. they are the same.
eg: App launch -> set Reed.shared.context -> start download.
eg: shutDown() -> set Reed.shared.context -> start download.
context usually used to separate different users.
eg: logout() -> shutDown() -> login() -> set Reed.shared.context.
2 downloadlistkey
downloadListKey is a porperty of ReedInfo.
A pair of context and downloadListKey define a downloadListKey, it has itself‘s max concurrent download count.
downloadlistkey usually used for different business eg:named PDF_LIST, MP3_LIST.
3 key
key is a porperty of ReedInfo, you must set every task different identifier key.
Notifications
Noti_ReedDownload_Add_To_Downlaod_List
Noti_ReedDownload_Start
Noti_ReedDownload_Progress
Noti_ReedDownload_Complete
Noti_ReedDownload_Fails
Noti_ReedDownload_Waiting
Noti_ReedDownload_Pause
Noti_ReedDownload_Delete
Noti_ReedDownload_FullSpace
Every notification contains a object, its type is ReedInfo.
If full space, Reed will post one or more notifications whose object is ReedInfo, and post 1 notification that object = nil.
Most commonly used API
APIs relate control
///Add a task to downloadlist
public func addToStartList(key:String, url:String, destinationFilePath:String,downloadListKey:String? = nil,md5:String? = nil,isReplace:Bool = false)
/// start download when added a task to downloadlist
public func start(_ key:String, isReplace:Bool = false)
/// Direct download. not recommend. Recommend use addToStartList and checkToStart.
public func start(key:String, url:String, destinationFilePath:String, downloadListKey:String? = nil,md5:String? = nil,isReplace:Bool = false)
/// batch start download
public func startBatch(keys:[String])
/// check to start. Go to "Introduce checkToStart()" on this ReadMe.
public func checkToStart()
/// check to start on this downloadList.
public func checkToStart(downloadListKey:String)
///isTryStart meens:If call checkToStart() after the action. usually use default value.
public func pause(_ key:String, isTryStart:Bool? = true)
public func pauseBatch(keys:[String],isTryStart:Bool? = true)
public func deleteBatch(keys:[String],isTryStart:Bool? = true)
public func delete(_ key:String,isTryStart:Bool? = true)
//Shutdown all tasks. But all status of tasks are not changed.
//Execute this when:logout;no network;go to background.
public func shutDown()
APIs relate status
/// is downloading progress
/// (Downloading, waiting, pause, failed)
public func isDownloadingProgress(_ key:String) -> Bool
/// is undownload (un add to download list, un start, no record on database)
public func isUnDownload(_ key:String) -> Bool
public func isComplete(_ key:String) -> Bool
public func isDownloading(_ key:String) -> Bool
public func isPause(_ key:String) -> Bool
public func isWaiting(_ key:String) -> Bool
public func isFailed(_ key:String) -> Bool
/// get download model with key
public func getDownloadInfo(key:String) -> ReedInfo?
/// get all models on this downloadListKey
public func getDownloadInfos(downloadListKey:String? = nil) -> [ReedInfo]
/// get all models on download progress(Downloading,Waiting,Pause,Failed)
public func getDownloadProgressInfos(downloadListKey:String? = nil) -> [ReedInfo]
/// get all complete models
public func getCompleteInfos(downloadListKey:String? = nil) -> [ReedInfo]
@objc public func getDownloadProgressCount(downloadListKey:String? = nil) -> Int
@objc public func getDownloadingCount(downloadListKey:String? = nil) -> Int
@objc public func getWaitingCount(downloadListKey:String? = nil) -> Int
@objc public func getPauseCount(downloadListKey:String? = nil) -> Int
Config
/// Concurrent max download count on one downloadlist,default value is 3
Reed.shared.maxCount
/// Retry count when md5 invalidate,default value is 3
Reed.shared.maxRetryCount
/// Set it before start download, default value is ""
public var context
/// min interval between two download progress notifications been post, default value is 0.3 seconds
Reed.shared.progressPostTimeInterval:TimeInterval
/// If you use CocoaLumberjack,Reed would use your CocoaLumberjack configration.
/// If you not use CocoaLumberjack, Reed would not print whenever what value of showLogger.
Reed.shared.showLogger:Bool = true
/// If you not use CocoaLumberjack,Call this method to config CocoaLumberjack
/// timeFormatter:Date message of every log,default value is "yyyy-MM-dd'T'HH:mm:ss.SSSZ" of Date()
public func configLogger(level:DDLogLevel? = .info, timeFormatter:(()->String)? = nil)
Requirements
- iOS 8.0+
- Xcode 10.2
- Swift 5
Installatio
Cocoapods
Aadd the following line to your Podfile:
pod "Reed"
Author
Kevin Zhou
- Email: [email protected]
- Facebook: wumingapie
- 微信&QQ: 458545592
License
Reed is available under the MIT license. See the LICENSE file for more info.