iOS怎么進行后臺下載,斷點下載

iOS怎么進行后臺下載,斷點下載

從iOS7以來,蘋果阿爸推出NSURLSession后,iOS現在可以實現真正的后臺下載。

一個NSURLSession對象可以協調一個或多個NSURLSessionTask對象,并且根據NSURLSessionTask創建的NSURLSessionConfiguration實現不同的功能,使用相同的配置,你也可以創建多組具有相關任務的NSURLSession對象,要利用后臺傳輸服務,你將會使用[NSURLSessionConfiguration backgroundSessionConfiguration]來創建一個會話配置,添加到后臺會話的任務在外部進程運行,即使應用程序被掛起,崩潰,或者被殺死,它依然會運行。

下面我們來看看如何使用NSURLSession

下載用到的委托方法

1:AppDelegate委托方法

//在應用處于后臺,且后臺任務下載完成時回調 - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler; ?????????????????

2:NSURLSession委托方法

/* 在任務下載完成、下載失敗 * 或者是應用被殺掉后,重新啟動應用并創建相關identifier的Session時調用 */ - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error; ?

/* 應用在后臺,而且后臺所有下載任務完成后,

* 在所有其他NSURLSession和NSURLSessionDownloadTask委托方法執行完后回調,

* 可以在該方法中做下載數據管理和UI刷新 ?*/-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession*)session;

注:最好將handleEventsForBackgroundURLSession中completionHandler保存,在該方法中待所有載數據管理和UI刷新做完后,再調用completionHandler()

NSURLSessionDownloadTask委托方法

/* 下載過程中調用,用于跟蹤下載進度

* bytesWritten為單次下載大小

* totalBytesWritten為當當前一共下載大小

* totalBytesExpectedToWrite為文件大小

*/-(void)URLSession:(NSURLSession*)sessiondownloadTask:(NSURLSessionDownloadTask*)downloadTaskdidWriteData:(int64_t)bytesWrittentotalBytesWritten:(int64_t)totalBytesWrittentotalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;

/* 下載恢復時調用

* 在使用downloadTaskWithResumeData:方法獲取到對應NSURLSessionDownloadTask,

* 并該task調用resume的時候調用

? */-(void)URLSession:(NSURLSession*)sessiondownloadTask:(NSURLSessionDownloadTask*)downloadTaskdidResumeAtOffset:(int64_t)fileOffsetexpectedTotalBytes:(int64_t)expectedTotalBytes;

//下載完成時調用- (void)URLSession:(NSURLSession*)session? ? ? downloadTask:(NSURLSessionDownloadTask*)downloadTaskdidFinishDownloadingToURL:(NSURL*)location;

注:在URLSession:downloadTask:didFinishDownloadingToURL方法中,location只是一個磁盤上該文件的臨時 URL,只是一個臨時文件,需要自己使用NSFileManager將文件寫到應用的目錄下(一般來說這種可以重復獲得的內容應該放到cache目錄下),因為當你從這個委托方法返回時,該文件將從臨時存儲中刪除。

創建后臺下載的操作步驟

后臺傳輸的的實現也十分簡單,簡單說分為三個步驟:

1:創建后臺下載用的NSURLSession對象,設置為后臺下載類型;

2:向這個對象中加入對應的傳輸的NSURLSessionTask,并開始下載;

3:在AppDelegate里實現handleEventsForBackgroundURLSession,以刷新UI及通知系統傳輸結束。

4:實現NSURLSessionDownloadDelegate中必要的代理

具體代碼實現

1:創建一個后臺下載對象用dispatch_once創建一個用于后臺下載對象,目的是為了保證identifier的唯一,文檔不建議對于相同的標識符 (identifier) 創建多個會話對象。這里創建并配置了NSURLSession,將通過backgroundSessionConfiguration其指定為后臺session并設定delegate。

- (NSURLSession*)backgroundURLSession {staticNSURLSession*session =nil;staticdispatch_once_tonceToken;dispatch_once(&onceToken, ^{NSString*identifier =@"com.yourcompany.appId.BackgroundSession";NSURLSessionConfiguration* sessionConfig = [NSURLSessionConfigurationbackgroundSessionConfigurationWithIdentifier:identifier]; session = [NSURLSessionsessionWithConfiguration:sessionConfig delegate:selfdelegateQueue:[NSOperationQueuemainQueue]]; });returnsession;}

2:向其中加入對應的傳輸用的NSURLSessionTask,并調用resume啟動下載。

- (void)beginDownloadWithUrl:(NSString*)downloadURLString {NSURL*downloadURL = [NSURLURLWithString:downloadURLString];NSURLRequest*request = [NSURLRequestrequestWithURL:downloadURL];NSURLSession*session = [selfbackgroundURLSession];NSURLSessionDownloadTask*downloadTask = [session downloadTaskWithRequest:request]; [downloadTask resume];}

3.在appDelegate中實現handleEventsForBackgroundURLSession,要注意的是,需要在handleEventsForBackgroundURLSession中必須重新建立一個后臺 session 的參照(可以用之前dispatch_once創建的對象),否則NSURLSessionDownloadDelegate和NSURLSessionDelegate方法會因為沒有 對 session 的 delegate 設置而不會被調用。然后保存completionHandler()。

- (void)application:(UIApplication*)applicationhandleEventsForBackgroundURLSession:(NSString*)identifier completionHandler:(void(^)())completionHandler {NSURLSession*backgroundSession = [selfbackgroundURLSession];NSLog(@"Rejoining session with identifier %@ %@", identifier, backgroundSession);// 保存 completion handler 以在處理 session 事件后更新 UI[selfaddCompletionHandler:completionHandler forSession:identifier]; }

- (void)addCompletionHandler:(CompletionHandlerType)handler forSession:(NSString*)identifier {if([self.completionHandlerDictionary objectForKey:identifier]) {NSLog(@"Error: Got multiple handlers for a single session identifier. This should not happen.\n"); } [self.completionHandlerDictionary setObject:handler forKey:identifier];}

注:handleEventsForBackgroundURLSession方法是在后臺下載的所有任務完成后才會調用。如果當后臺傳輸完成時,如果應用程序已經被殺掉,iOS將會在后臺啟動該應用程序,下載相關的委托方法會在application:didFinishLaunchingWithOptions:方法被調用之后被調用。

4:實現URLSessionDidFinishEventsForBackgroundURLSession,待所有數據處理完成,UI刷新之后在改方法中在調用之前保存的completionHandler()。

//NSURLSessionDelegate委托方法,會在NSURLSessionDownloadDelegate委托方法后執行- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession*)session {NSLog(@"Background URL session %@ finished events.\n", session);if(session.configuration.identifier) {// 調用在 -application:handleEventsForBackgroundURLSession: 中保存的 handler[selfcallCompletionHandlerForSession:session.configuration.identifier]; }} - (void)callCompletionHandlerForSession:(NSString*)identifier { CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey: identifier];if(handler) { [self.completionHandlerDictionary removeObjectForKey: identifier];NSLog(@"Calling completion handler for session %@", identifier); handler(); }}

關于斷點下載可能還會問到的問題

如何暫停下載,暫停后,如何繼續下載?有兩種方法

@第一種,使用cancelByProducingResumeData

/* 對某一個NSURLSessionDownloadTask取消下載,取消后會回調給我們 resumeData,

? ? * resumeData包含了下載任務的一些狀態,之后可以用戶恢復下載

? */- (void)cancelByProducingResumeData:(void(^)(NSData* resumeData))completionHandler;

調用該方法會觸發以下方法,會附帶resumeData,用于恢復。

- (void)URLSession:(NSURLSession*)session task:(NSURLSessionTask*)taskdidCompleteWithError:(NSError*)error

對應恢復方法

//通過之前保存的resumeData,獲取斷點的NSURLSessionTask,調用resume恢復下載NSURLSessionDownloadTask*task = [[selfbackgroundURLSession] downloadTaskWithResumeData:resumeData];[task resume];

第二種,使用NSURLSessionDownloadTask的suspend方法

//暫停[self.downloadTask suspend];

//恢復[self.downloadTask resume];

通過以上的兩個方法,就可以實現下載的暫停與恢復下載了

下載失敗后,如何恢復下載?--下載失敗后,可以通過以下代碼來恢復下載

/* 該方法下載成功和失敗都會回調,只是失敗的是error是有值的,

? * 在下載失敗時,error的userinfo屬性可以通過NSURLSessionDownloadTaskResumeData

? * 這個key來取到resumeData(和上面的resumeData是一樣的),再通過resumeData恢復下載

? */- (void)URLSession:(NSURLSession*)sessiona? ? ? ? ? ? ? task:(NSURLSessionTask*)taskdidCompleteWithError:(NSError*)error {if(error) {// check if resume data are availableif([error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData]) {NSData*resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData];NSURLSessionTask*task = [[selfbackgroundURLSession] downloadTaskWithResumeData:resumeData];? ? ? ? ? ? [task resume];? ? ? ? }? ? }}

應用被用戶殺掉后,如何恢復之前的下載?

在應用被殺掉前,iOS系統保存應用下載sesson的信息,在重新啟動應用,并且創建和之前相同identifier的session時(蘋果通過identifier找到對應的session數據),iOS系統會對之前下載中的任務進行依次回調URLSession:task:didCompleteWithError:方法,之后可以使用上面提到的下載失敗時的處理方法進行恢復下載


http://www.lxweimin.com/p/1211cf99dfc3

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容