目錄
NSURLSession 的優(yōu)勢(shì)
NSURLSessionTask 的子類
NSURLSessionDataTask 發(fā)送 GET 請(qǐng)求
NSURLSessionDataTask 發(fā)送 POST 請(qǐng)求
NSURLSessionDataTask 設(shè)置代理發(fā)送請(qǐng)求
設(shè)置代理之后的強(qiáng)引用問(wèn)題
NSURLSessionDataTask 簡(jiǎn)單下載
NSURLSessionDownloadTask 簡(jiǎn)單下載
dataTask 和 downloadTask 下載對(duì)比
寫(xiě)在最后
【補(bǔ)充】NSURLSession 詳解離線斷點(diǎn)下載的實(shí)現(xiàn)
NSURLSession 支持 http2.0 協(xié)議
在處理下載任務(wù)的時(shí)候可以直接把數(shù)據(jù)下載到磁盤
支持后臺(tái)下載|上傳
同一個(gè) session 發(fā)送多個(gè)請(qǐng)求故响,只需要建立一次連接(復(fù)用了TCP)
提供了全局的 session 并且可以統(tǒng)一配置纷捞,使用更加方便
下載的時(shí)候是多線程異步處理,效率更高
NSURLSessionTask 是一個(gè)抽象類被去,如果要使用那么只能使用它的子類
NSURLSessionTask 有兩個(gè)子類
NSURLSessionDataTask,可以用來(lái)處理一般的網(wǎng)絡(luò)請(qǐng)求,如 GET | POST 請(qǐng)求等
NSURLSessionDataTask 有一個(gè)子類為 NSURLSessionUploadTask,用于處理上傳請(qǐng)求的時(shí)候有優(yōu)勢(shì)
NSURLSessionDownloadTask,主要用于處理下載請(qǐng)求奖唯,有很大的優(yōu)勢(shì)
NSURLSession 的子類
NSURLSessionDataTask 發(fā)送 GET 請(qǐng)求
發(fā)送 GET 請(qǐng)求的步驟非常簡(jiǎn)單惨缆,只需要兩步就可以完成:
使用 NSURLSession 對(duì)象創(chuàng)建 Task
執(zhí)行 Task
//確定請(qǐng)求路徑NSURL*url = [NSURLURLWithString:@"http://120.25.226.186:32812/login?username=520&pwd=520&type=JSON"];//創(chuàng)建 NSURLSession 對(duì)象NSURLSession*session = [NSURLSessionsharedSession];/**
根據(jù)對(duì)象創(chuàng)建 Task 請(qǐng)求
url? 方法內(nèi)部會(huì)自動(dòng)將 URL 包裝成一個(gè)請(qǐng)求對(duì)象(默認(rèn)是 GET 請(qǐng)求)
completionHandler? 完成之后的回調(diào)(成功或失敗)
param data? ? 返回的數(shù)據(jù)(響應(yīng)體)
param response 響應(yīng)頭
param error? ? 錯(cuò)誤信息
*/NSURLSessionDataTask*dataTask = [session dataTaskWithURL:url completionHandler:? ? ? ? ? ? ^(NSData* _Nullable data,NSURLResponse* _Nullable response,NSError* _Nullable error) {//解析服務(wù)器返回的數(shù)據(jù)NSLog(@"%@", [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding]);//默認(rèn)在子線程中解析數(shù)據(jù)NSLog(@"%@", [NSThreadcurrentThread]); }];//發(fā)送請(qǐng)求(執(zhí)行Task)[dataTask resume];
NSURLSessionDataTask 發(fā)送 POST 請(qǐng)求
發(fā)送 POST 請(qǐng)求的步驟與發(fā)送 GET 請(qǐng)求一樣:
使用 NSURLSession 對(duì)象創(chuàng)建 Task
執(zhí)行 Task
//確定請(qǐng)求路徑NSURL*url = [NSURLURLWithString:@"http://120.25.226.186:32812/login"];//創(chuàng)建可變請(qǐng)求對(duì)象NSMutableURLRequest*requestM = [NSMutableURLRequestrequestWithURL:url];//修改請(qǐng)求方法requestM.HTTPMethod=@"POST";//設(shè)置請(qǐng)求體requestM.HTTPBody= [@"username=520&pwd=520&type=JSON"dataUsingEncoding:NSUTF8StringEncoding];//創(chuàng)建會(huì)話對(duì)象NSURLSession*session = [NSURLSessionsharedSession];//創(chuàng)建請(qǐng)求 TaskNSURLSessionDataTask*dataTask = [session dataTaskWithRequest:requestM completionHandler:? ? ? ? ? ? ^(NSData* _Nullable data,NSURLResponse* _Nullable response,NSError* _Nullable error) {//解析返回的數(shù)據(jù)NSLog(@"%@", [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding]); }];//發(fā)送請(qǐng)求[dataTask resume];
NSURLSessionDataTask 設(shè)置代理發(fā)送請(qǐng)求
創(chuàng)建 NSURLSession 對(duì)象設(shè)置代理
使用 NSURLSession 對(duì)象創(chuàng)建 Task
執(zhí)行 Task
//確定請(qǐng)求路徑NSURL*url = [NSURLURLWithString:@"http://120.25.226.186:32812/login"];//創(chuàng)建可變請(qǐng)求對(duì)象NSMutableURLRequest*requestM = [NSMutableURLRequestrequestWithURL:url];//設(shè)置請(qǐng)求方法requestM.HTTPMethod=@"POST";//設(shè)置請(qǐng)求體requestM.HTTPBody= [@"username=520&pwd=520&type=JSON"dataUsingEncoding:NSUTF8StringEncoding];//創(chuàng)建會(huì)話對(duì)象丰捷,設(shè)置代理/**
第一個(gè)參數(shù):配置信息
第二個(gè)參數(shù):設(shè)置代理
第三個(gè)參數(shù):隊(duì)列坯墨,如果該參數(shù)傳遞nil 那么默認(rèn)在子線程中執(zhí)行
*/NSURLSession*session = [NSURLSessionsessionWithConfiguration:[NSURLSessionConfigurationdefaultSessionConfiguration]? ? ? ? ? ? ? ? ? ? ? ? ? ? ? delegate:selfdelegateQueue:nil];//創(chuàng)建請(qǐng)求 TaskNSURLSessionDataTask*dataTask = [session dataTaskWithRequest:requestM];//發(fā)送請(qǐng)求[dataTask resume];
遵守協(xié)議,實(shí)現(xiàn)代理方法(常用的有三種代理方法)
-(void)URLSession:(NSURLSession*)session dataTask:(nonnullNSURLSessionDataTask*)dataTask didReceiveResponse:(nonnullNSURLResponse*)response completionHandler:(nonnullvoid(^)(NSURLSessionResponseDisposition))completionHandler {//子線程中執(zhí)行NSLog(@"接收到服務(wù)器響應(yīng)的時(shí)候調(diào)用 -- %@", [NSThreadcurrentThread]);self.dataM= [NSMutableDatadata];//默認(rèn)情況下不接收數(shù)據(jù)//必須告訴系統(tǒng)是否接收服務(wù)器返回的數(shù)據(jù)completionHandler(NSURLSessionResponseAllow);}-(void)URLSession:(NSURLSession*)session dataTask:(NSURLSessionDataTask*)dataTask didReceiveData:(NSData*)data {NSLog(@"接受到服務(wù)器返回?cái)?shù)據(jù)的時(shí)候調(diào)用,可能被調(diào)用多次");//拼接服務(wù)器返回的數(shù)據(jù)[self.dataMappendData:data];}-(void)URLSession:(NSURLSession*)session task:(NSURLSessionTask*)task didCompleteWithError:(NSError*)error {NSLog(@"請(qǐng)求完成或者是失敗的時(shí)候調(diào)用");//解析服務(wù)器返回?cái)?shù)據(jù)NSLog(@"%@", [[NSStringalloc] initWithData:self.dataMencoding:NSUTF8StringEncoding]);}
NSURLSession 對(duì)象在使用的時(shí)候病往,如果設(shè)置了代理捣染,那么 session 會(huì)對(duì)代理對(duì)象保持一個(gè)強(qiáng)引用,在合適的時(shí)候應(yīng)該主動(dòng)進(jìn)行釋放
可以在控制器調(diào)用 viewDidDisappear 方法的時(shí)候來(lái)進(jìn)行處理停巷,可以通過(guò)調(diào)用 invalidateAndCancel 方法或者是 finishTasksAndInvalidate 方法來(lái)釋放對(duì)代理對(duì)象的強(qiáng)引用
invalidateAndCancel 方法直接取消請(qǐng)求然后釋放代理對(duì)象
finishTasksAndInvalidate 方法等請(qǐng)求完成之后釋放代理對(duì)象耍攘。
[self.sessionfinishTasksAndInvalidate];
NSURLSessionDataTask 簡(jiǎn)單下載
在前面請(qǐng)求數(shù)據(jù)的時(shí)候就相當(dāng)于一個(gè)簡(jiǎn)單的下載過(guò)程,NSURLSessionDataTask 下載文件具體的步驟與上類似:
使用 NSURLSession 對(duì)象創(chuàng)建一個(gè) Task 請(qǐng)求
執(zhí)行請(qǐng)求
[[[NSURLSessionsharedSession] dataTaskWithURL:[NSURLURLWithString:@"http://120.25.226.186:32812/resources/images/minion_01.png"]? ? ? completionHandler:^(NSData* _Nullable data,NSURLResponse* _Nullable response,NSError* _Nullable error) {//解析數(shù)據(jù)UIImage*image = [UIImageimageWithData:data];//回到主線程設(shè)置圖片dispatch_async(dispatch_get_main_queue(), ^{self.imageView.image= image;? ? }); }] resume];
NSURLSessionDownloadTask 簡(jiǎn)單下載
使用 NSURLSession 對(duì)象創(chuàng)建下載請(qǐng)求
在下載請(qǐng)求中移動(dòng)文件到指定位置
執(zhí)行請(qǐng)求
//確定請(qǐng)求路徑NSURL*url = [NSURLURLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"];//創(chuàng)建請(qǐng)求對(duì)象NSURLRequest*request = [NSURLRequestrequestWithURL:url];//創(chuàng)建會(huì)話對(duì)象NSURLSession*session = [NSURLSessionsharedSession];//創(chuàng)建會(huì)話請(qǐng)求//優(yōu)點(diǎn):該方法內(nèi)部已經(jīng)完成了邊接收數(shù)據(jù)邊寫(xiě)沙盒的操作畔勤,解決了內(nèi)存飆升的問(wèn)題NSURLSessionDownloadTask*downTask = [session downloadTaskWithRequest:request? ? ? completionHandler:^(NSURL* _Nullable location,NSURLResponse* _Nullable response,NSError* _Nullable error) {//默認(rèn)存儲(chǔ)到臨時(shí)文件夾 tmp 中蕾各,需要剪切文件到 cacheNSLog(@"%@", location);//目標(biāo)位置NSString*fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES) lastObject]? ? ? ? ? ? ? ? ? ? ? ? ? stringByAppendingPathComponent:response.suggestedFilename];/**
fileURLWithPath:有協(xié)議頭
URLWithString:無(wú)協(xié)議頭
*/[[NSFileManagerdefaultManager] moveItemAtURL:location toURL:[NSURLfileURLWithPath:fullPath] error:nil]; }];//發(fā)送請(qǐng)求[downTask resume];
以上方法無(wú)法監(jiān)聽(tīng)下載進(jìn)度,如要獲取下載進(jìn)度庆揪,可以使用代理的方式進(jìn)行下載式曲。
dataTask 和 downloadTask 下載對(duì)比
NSURLSessionDataTask
下載文件可以實(shí)現(xiàn)離線斷點(diǎn)下載,但是代碼相對(duì)復(fù)雜
NSURLSessionDownloadTask
下載文件可以實(shí)現(xiàn)斷點(diǎn)下載缸榛,但不能離線斷點(diǎn)下載
內(nèi)部已經(jīng)完成了邊接收數(shù)據(jù)邊寫(xiě)入沙盒的操作
解決了下載大文件時(shí)的內(nèi)存飆升問(wèn)題
關(guān)于使用 NSURLSession 進(jìn)行上傳文件操作吝羞,我只想說(shuō)真的很麻煩,建議大家時(shí)間充沛且有興趣的可以研究一下内颗,如果不想研究也是可以的钧排,繼續(xù)使用我們偉大的 AFN 框架就好。至于 AFN 框架的使用均澳,這里就不贅述了卖氨,后期如果有時(shí)間會(huì)更新一些常用的 AFN 使用方法会烙,敬請(qǐng)期待。
附:使用 NSURLSession 上傳文件主要步驟及注意點(diǎn)
主要步驟:
確定上傳請(qǐng)求的路徑( NSURL )
創(chuàng)建可變的請(qǐng)求對(duì)象( NSMutableURLRequest )
修改請(qǐng)求方法為 POST
設(shè)置請(qǐng)求頭信息(告知服務(wù)器端這是一個(gè)文件上傳請(qǐng)求)
按照固定的格式拼接要上傳的文件等參數(shù)
根據(jù)請(qǐng)求對(duì)象創(chuàng)建會(huì)話對(duì)象( NSURLSession 對(duì)象)
根據(jù) session 對(duì)象來(lái)創(chuàng)建一個(gè) uploadTask 上傳請(qǐng)求任務(wù)
執(zhí)行該上傳請(qǐng)求任務(wù)(調(diào)用 resume 方法)
得到服務(wù)器返回的數(shù)據(jù)筒捺,解析數(shù)據(jù)(上傳成功 | 上傳失敯啬濉)
注意點(diǎn):
創(chuàng)建可變的請(qǐng)求對(duì)象,因?yàn)樾枰薷恼?qǐng)求方法為 POST系吭,設(shè)置請(qǐng)求頭信息
設(shè)置請(qǐng)求頭這個(gè)步驟可能會(huì)被遺漏
要處理上傳參數(shù)的時(shí)候五嫂,一定要按照固定的格式來(lái)進(jìn)行拼接
需要采用合適的方法來(lái)獲得上傳文件的二進(jìn)制數(shù)據(jù)類型( MIMEType,獲取方式如下)
對(duì)著該文件發(fā)送一個(gè)網(wǎng)絡(luò)請(qǐng)求肯尺,接收到該請(qǐng)求響應(yīng)的時(shí)候沃缘,可以通過(guò)響應(yīng)頭信息中的 MIMEType 屬性得到
使用通用的二進(jìn)制數(shù)據(jù)類型表示任意的二進(jìn)制數(shù)據(jù) application/octet-stream
調(diào)用 C 語(yǔ)言的 API 來(lái)獲取
[self mimeTypeForFileAtPath:@"此處為上傳文件的路徑"]
文/Mortal_Master(簡(jiǎn)書(shū)作者)
原文鏈接:http://www.reibang.com/p/b0ddadd34037
著作權(quán)歸作者所有,轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)则吟,并標(biāo)注“簡(jiǎn)書(shū)作者”槐臀。