ios - NSURLSession的使用

一. 背景

NSURLSession是蘋果在iOS7后推出的通過HTTP協(xié)議下載數(shù)據(jù)的API,該類提供了大量的代理方法偶摔,來支持認證和后臺下載功能瞬内。
使用NSURLSession須知:
a> 我們的應(yīng)用會創(chuàng)建一系列的對話,每個對話負責一組的數(shù)據(jù)傳輸任務(wù),并且會添加一系列的任務(wù)灿巧,每個任務(wù)代表著一個URL請求铺坞。
b> NSURLSession的API是異步的劲够。
c> NSURLSession的使用分成:1.系統(tǒng)代理的方式(需要提供一個請求完成后處理的block)2. 自定義代理的方式(執(zhí)行代理方法來處理請求成功或失敼纭)
d> NSURLSession支持取消聊疲、恢復(fù)茬底、掛起操作,以及斷掉續(xù)傳的功能

二. NSURLSession

NSURLSession根據(jù)配置對象(NSURLSessionConfiguration)分為三大類型
  1. 默認會話(defaultSessionConfiguration):存儲cookie(緩存)在磁盤中获洲,存儲證書在用戶keychain
  2. 后臺會話(backgroundSessionConfiguration):存儲cookie(緩存)在磁盤中阱表,存儲證書在用戶keychain。后臺會添加獨立的進程來處理數(shù)據(jù)傳輸任務(wù)
  3. 短暫會話(ephemeralSessionConfiguration):緩存和證書都存在RAM中,會話結(jié)束最爬,它們就自動釋放
任務(wù)類型也分為三大類
  1. dataTask:使用NSData對象進行上傳和下載數(shù)據(jù)涉馁;數(shù)據(jù)可一次性返回,也可以分片段返回烂叔;返回的數(shù)據(jù)不是進行文件存儲谨胞,所以不支持后臺會話(iOS8后支持 備注:主要用于一些小數(shù)據(jù)請求,或大文件的斷點續(xù)傳下載
  2. downloadTask:以文件的形式接收數(shù)據(jù)蒜鸡,當程序不運行時支持后臺下載
  3. uploadTask:以文件的形式上傳數(shù)據(jù)胯努,支持后臺下載
簡單使用
1. 系統(tǒng)代理的方式

a>. dataTask

 //  1.創(chuàng)建NSURLSession單例對象
    NSURLSession *session = [NSURLSession sharedSession];
    
    //  2.添加dataTask任務(wù)(1>. 通過NSURLRequest方式 ;2>. 通過NSURL方式(內(nèi)部進行封裝成NSURLRequest對象))
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://xxx"]];
    /*
     POST請求請加這兩句
     request.HTTPMethod = @"POST";
     request.HTTPBody = [@"參數(shù)" dataUsingEncoding:NSUTF8StringEncoding];
     */
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    /*
     data:請求成功后返回的數(shù)據(jù)
     response:請求頭
     error:如果有值說明請求失敗
     */
    }];
    //或則
    //    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"http://xxx"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    //
    //    }];
    
    //  3.開始任務(wù)
    [dataTask resume];

b>. downLoadTask
內(nèi)部已經(jīng)實現(xiàn)邊下載邊寫入temp文件中逢防,由于temp中的文件易清除叶沛,所以須手動將文件剪切到合適的沙河目錄 缺點:無法監(jiān)控下載進度

    //  1.創(chuàng)建NSURLSession單例對象
    NSURLSession *session = [NSURLSession sharedSession];
    
    //  2.添加downloadTask任務(wù)(1>. 通過NSURLRequest方式 ;2>. 通過NSURL方式(內(nèi)部進行封裝成NSURLRequest對象))
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://xxx"]];
    /*
     POST請求請加這兩句
     request.HTTPMethod = @"POST";
     request.HTTPBody = [@"參數(shù)" dataUsingEncoding:NSUTF8StringEncoding];
     */
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        /*
         location:下載的文件的保存地址,默認是temp
         */
    }];
    //或則
//    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://xxx"] completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//        
//    }];

    //  3.開始任務(wù)
    [downloadTask resume];

c>. upLoadTask

    //  1.創(chuàng)建NSURLSession單例對象
    NSURLSession *session = [NSURLSession sharedSession];
    
    //  2.添加uploadTask任務(wù)
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://xxx"]];
    NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:[NSURL URLWithString:@"daf.af.af.3422"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        
    }];
    //  3.開始任務(wù)
    [uploadTask resume];
2.通過設(shè)置配置實現(xiàn)代理方法的方式

a>. dataTask下載文件

    //  1.創(chuàng)建默認配置的NSURLSession對象
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    /*
     NSURLSessionConfiguration:session對象的全局配置設(shè)置忘朝,一般使用默認配置就可以
     delegate:設(shè)置代理
     delegateQueue:代理方法在哪個隊列中執(zhí)行(在哪個線程中調(diào)用),如果是主隊列那么在主線程中執(zhí)行灰署,如果是非主隊列,那么在子線程中執(zhí)行
     */
    //  2.創(chuàng)建一個Task, 請求方法為get和post均可
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:@"http://xxxx"]];
    
    //  3.執(zhí)行任務(wù)(可暫停局嘁、取消溉箕、恢復(fù)等)
    [dataTask resume];  // [dataTask suspend] [dataTask cancel]; 

//  4. 遵守代理協(xié)議,實現(xiàn)代理方法(3個相關(guān)的代理方法)

 /* 1.當接收到服務(wù)器響應(yīng)的時候調(diào)用 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
    
    //  通過該block回調(diào)悦昵,告訴服務(wù)器端是否接收返回的數(shù)據(jù)
    completionHandler(NSURLSessionResponseAllow);
    /*
     NSURLSessionResponseCancel = 0, 取消任務(wù)
     NSURLSessionResponseAllow = 1,  接收任務(wù)
     NSURLSessionResponseBecomeDownload = 2, 轉(zhuǎn)變成下載
     NSURLSessionResponseBecomeStream NS_ENUM_AVAILABLE(10_11, 9_0) = 3, 轉(zhuǎn)變成流
     */
}

/* 2.當接收到服務(wù)器返回的數(shù)據(jù)時調(diào)用 該方法可能會被調(diào)用多次 */
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {

}

/* 3.當請求完成之后調(diào)用該方法 不論是請求成功還是請求失敗都調(diào)用該方法肴茄,如果請求失敗,那么error對象有值但指,否則那么error對象為空 */
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    
}

b>. downloadTask下載文件

和dataTask一樣只是代理方法有所區(qū)別

//  4. 遵守代理協(xié)議寡痰,實現(xiàn)代理方法(3個相關(guān)的代理方法)

 /* 1.可以在該方法中監(jiān)聽文件下載的進度,該方法會被調(diào)用多次
 */
-(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {  
 
}

/* 2.恢復(fù)下載的時候調(diào)用該方法 */
-(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes {

}

/* 3.下載完成之后調(diào)用該方法 */
-(void)URLSession:(nonnull NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(nonnull NSURL *)location {
    
}
/* 4.請求完成之后調(diào)用如果請求失敗棋凳,那么error有值 */
-(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error {
    
}

注意:

  1. 如果通過[downloadTask cancel]取消任務(wù)拦坠,那么任務(wù)不能恢復(fù)了
  2. 通過以下方法暫停,那么該方法會以resumeData保存當前文件的已經(jīng)下載數(shù)據(jù)剩岳,任務(wù)可以恢復(fù)下載
[self.downloadTask cancelByProducingResumeData:^(NSData * __nullable resumeData) {
    self.resumeData = resumeData;
}];

恢復(fù)下載方法

self.downloadTask=[self.session downloadTaskWithResumeData:self.resumeData];
 [self.downloadTask resume];
  1. 缺點
    01 如果用戶點擊暫停之后退出程序贞滨,那么需要把恢復(fù)下載的數(shù)據(jù)寫一份到沙盒,代碼復(fù)雜度更
    02 如果用戶在下載中途未保存恢復(fù)下載數(shù)據(jù)即退出程序拍棕,則不具備可操作性

c>. uploadTask上傳文件

    //1.創(chuàng)建session
    self.session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    //2.創(chuàng)建task
    //2.1 創(chuàng)建請求對象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://xxxxx"]];
    //2.2 設(shè)置請求方法
    request.HTTPMethod = @"POST";
    
    //2.3.設(shè)置請求頭
    NSString *header = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",str];
    [request setValue:header forHTTPHeaderField:@"Content-Type"];
    //2.4設(shè)置文件上傳的文件內(nèi)容
    NSURLSessionUploadTask *uploadTask = [self.session uploadTaskWithRequest:request fromData:data];
     [uploadTask resume];

// 4. 遵守代理協(xié)議晓铆,實現(xiàn)代理方法

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
{
}

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
}
后臺會話

當我們的運用退出,如果后臺下載任務(wù)完成或則需要證書時莫湘,后臺自動重啟我們的運用尤蒿,同時調(diào)用UIApplicationDelegate對象application:handlerEventsForBackgroundURLSession:completionHandler:方法,這個方法會提供session的標識幅垮,然后我們要利用session的標識創(chuàng)建后臺配置腰池,繼而創(chuàng)建新的后臺會話,與后臺的activity關(guān)聯(lián)。當后臺下載任務(wù)完成時示弓,會調(diào)用后臺session的代理方法URLSessioinDidFinishEventsForBackgroundURLSession:然后調(diào)用存儲的完成處理

如果在程序掛起時有任何任務(wù)完成讳侨,則會調(diào)用URLSession:downloadTask:didFinishDownloadingToURL:方法。同樣的奏属,如果任務(wù)需要證書跨跨,則NSURLSession對象會在適當?shù)臅r候調(diào)用URLSession:task:didReceiveChallenge:completionHandler: 和URLSession:didReceiveChallenge:completionHandler:方法。

(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler
{
    NSURLSessionConfiguration *backgroundConfigObject = [NSURLSessionConfiguration backgroundSessionConfiguration:identifier];
    
    URLSession *sessionDelegate = [[URLSession alloc] init];
    
    NSURLSession *backgroundSession = [NSURLSession sessionWithConfiguration:backgroundConfigObject
                                                                    delegate:sessionDelegate
                                                               delegateQueue:[NSOperationQueue mainQueue]];
    
    [sessionDelegate addCompletionHandler:completionHandler forSession:identifier];
}
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
    NSLog(@"background url session %@", session);
    
    if (session.configuration.identifier)
    {
        [self callCompletionHandlerForSession:session.configuration.identifier];
    }
}

- (void)callCompletionHandlerForSession:(NSString *)identifier
{
    CompletionHandlerType handler = [self.completionHandlerDictionary objectForKey:identifier];
    
    if (handler) {
        [self.completionHandlerDictionary removeObjectForKey:identifier];
        
        handler();
    }
}
注意:

NSURLSession對象的釋放

 -(void)dealloc { 
//在最后的時候應(yīng)該把session釋放囱皿,以免造成內(nèi)存泄露 
// NSURLSession設(shè)置過代理后勇婴,需要在最后(比如控制器銷毀的時候)調(diào)用session的invalidateAndCancel或者resetWithCompletionHandler,才不會有內(nèi)存泄露 
// [self.session invalidateAndCancel]; 
[self.session resetWithCompletionHandler:^{

    NSLog(@"釋放---");
}];
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嘱腥,一起剝皮案震驚了整個濱河市耕渴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌齿兔,老刑警劉巖橱脸,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異分苇,居然都是意外死亡添诉,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門医寿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來栏赴,“玉大人,你說我怎么就攤上這事糟红“剩” “怎么了乌叶?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵盆偿,是天一觀的道長。 經(jīng)常有香客問我准浴,道長事扭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任乐横,我火速辦了婚禮求橄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘葡公。我一直安慰自己罐农,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布催什。 她就那樣靜靜地躺著涵亏,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上气筋,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天拆内,我揣著相機與錄音,去河邊找鬼宠默。 笑死麸恍,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的搀矫。 我是一名探鬼主播抹沪,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼瓤球!你這毒婦竟也來了采够?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤冰垄,失蹤者是張志新(化名)和其女友劉穎蹬癌,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體虹茶,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡逝薪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝴罪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片董济。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖要门,靈堂內(nèi)的尸體忽然破棺而出虏肾,到底是詐尸還是另有隱情,我是刑警寧澤欢搜,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布封豪,位于F島的核電站,受9級特大地震影響炒瘟,放射性物質(zhì)發(fā)生泄漏吹埠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一疮装、第九天 我趴在偏房一處隱蔽的房頂上張望缘琅。 院中可真熱鬧,春花似錦廓推、人聲如沸刷袍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽呻纹。三九已至鸽心,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間居暖,已是汗流浹背顽频。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留太闺,地道東北人糯景。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像省骂,于是被迫代替她去往敵國和親蟀淮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容