? ? ? ? 最近想封裝一個多任務斷點下載供項目使用,想?yún)⒖季W(wǎng)上是否有好的案例振惰,幾乎所有的下載相關都看了大同小異但是都不是很滿意歌溉,唯獨有個swift的demo引起了我的注意,有需要的可以查看Tiercel骑晶,但是該demo是純swift開發(fā)痛垛,iOS想使用需要橋接草慧,為了盡量減少混合代碼,想自己圍繞該demo樣式寫一份純OC示例榜晦,目前demo尚未全部完成冠蒋,后續(xù)會持續(xù)更新ZWDownload。以下附demo原型:
以下是著重講解項目中需要注意的點乾胶,當你了解這些點后抖剿,只要時間充足,你也能封裝一個理想的多任務下載管理器:
1.所需下載資源的總大惺读:
? ? ? ? 資源大小的生成方式有2種斩郎,第一種也是最簡單的當然是獲取下載資源的同時讓服務端告知總資源的大小喻频;第二種可以在創(chuàng)建任務的時候先建立task缩宜,在獲取資源反饋的時候進行掛起,這樣就能獲取每個資源的詳細信息(包括大猩隆)锻煌,累計所有待下載的資源的大小姻蚓;
2.進度:
? ? ? ? 進度分為單任務進度和多任務進度:
? ??????1).單任務進度:也是我們下載中最常見的下載的文件占當前網(wǎng)絡資源大小的百分比宋梧;
? ? ? ? 2).多任務進度:
? ? ? ? ? ? ? ? ? 第一種也是之前見過最多的,當一個資源下載完成后進度加多少狰挡,這樣存在的弊端? ? ? ? ? ? ?就是當文件的大小存在嚴重差異的時候捂龄,或者網(wǎng)絡不穩(wěn)定時候會存在卡在某個百分比進? ? ? ? ? ? 度,這也是很不人性化的加叁;
? ? ? ? ? ? ? ? ?第二種方式比較人性化倦沧,但是存在諸多計算消耗,視自己需要它匕≌谷冢可以當每獲取一個? ? ? ? ? ? 下載片段的時候便更新總的已下載文件大小(獲取大小這不用介紹了吧)豫柬,然后根據(jù)總? ? ? ? ? ? 的大小進行計算告希,這時候的進度是非常準確的。
備注:如果想像上面一樣轮傍,按照KB、M這種方式顯示進度為啥不用+ (NSString *)stringFromByteCount:(long long)byteCount countStyle:(NSByteCountFormatterCountStyle)countStyle試試呢首装?
3.下載速度:
? ? ? ? 下載速度是個取舍問題创夜,我們可以在每次更新下載片段的時候計算出時間差與片段的大小,這樣能精確的計算出下載速度仙逻,憑借定時器每秒獲取一次速度就行驰吓,但是這確實太沒趣了涧尿,做了很多沒必要的計算,如果我本來就不需要下載進度是不是多計算了很多檬贰?
? ? ? ? 合理的方式應該是設置是否需要下載速度開關姑廉,如果需要,每秒更新之前已下載大小與目前更新大形痰印(不要用NSTimer桥言,你懂的),然后計算葵礼,如果覺得這算0.5秒前的速度不滿意号阿,你也可以將時間縮短,也就是越準確你計算的越多鸳粉,還要做成每秒取一次操作扔涧,當然用戶也不會糾結(jié)這點精度。
4.剩余時間:
? ? ? ? 剩余時間是一個附加邏輯届谈,當你能計算出總的下載速度的時候枯夜,通過總的資源大小可以很簡單的計算出;
5.最大并發(fā)數(shù)量:
? ? ? ? 最大并發(fā)數(shù)可以手動控制最大并發(fā)的數(shù)量艰山。目前iPhone的處理器是多核(2個湖雹、4個),適當?shù)牟l(fā)可以提高效率程剥,但是無節(jié)制地并發(fā)劝枣,如將大量任務不加思索就用并發(fā)隊列來執(zhí)行,這只會大量增加線程數(shù)织鲸,搶占CPU資源舔腾,甚至會擠占掉主線程的 CPU 資源(極端情況)為此我們很有必要自己設置最大并發(fā)數(shù)量。設置并發(fā)數(shù)量最常用的方式就是使用信號量來控制搂擦。由于任務可以動態(tài)操作稳诚,所以這里可以使用隊列或者數(shù)組進行手動控制。
6.斷點續(xù)傳:
? ? ? ? 斷點續(xù)傳就比較簡單了瀑踢,只需要實時記錄下載鏈接對應的本地文件位置與已下載大小扳还,當重新打算下載的時候通過以下方法繼續(xù)下載之前未下載完的資源。
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
[request setValue:range forHTTPHeaderField:@"Range"];