因爲傲嬌的蘋果在 iOS9 以後已經放棄了 NSURLConnection,因此在如今的實際開發中,除了你們常見的 AFN 框架,通常使用的是 iOS7 以後推出的 NSURLSession,做爲一名 iOS 開發人員,若是你只知道 AFN 框架來進行網絡請求,那就只能說是 too young too simple,sometimes naive。服務器
原本想建立一個目錄跳轉的,好像簡書不支持,只好做罷,有哪位大神知道怎麼在簡書支持目錄跳轉的,但願不吝賜教!網絡
NSURLSession 的優點session
NSURLSessionTask 的子類多線程
NSURLSessionDataTask 發送 GET 請求app
NSURLSessionDataTask 發送 POST 請求框架
NSURLSessionDataTask 設置代理髮送請求異步
設置代理以後的強引用問題async
NSURLSessionDataTask 簡單下載url
NSURLSessionDownloadTask 簡單下載spa
dataTask 和 downloadTask 下載對比
寫在最後
NSURLSession 支持 http2.0 協議
在處理下載任務的時候能夠直接把數據下載到磁盤
支持後臺下載|上傳
同一個 session 發送多個請求,只須要創建一次鏈接(複用了TCP)
提供了全局的 session 而且能夠統一配置,使用更加方便
下載的時候是多線程異步處理,效率更高
NSURLSessionTask 是一個抽象類,若是要使用那麼只能使用它的子類
NSURLSessionTask 有兩個子類
NSURLSessionDataTask,能夠用來處理通常的網絡請求,如 GET | POST 請求等
NSURLSessionDataTask 有一個子類爲 NSURLSessionUploadTask,用於處理上傳請求的時候有優點
NSURLSessionDownloadTask,主要用於處理下載請求,有很大的優點
NSURLSession 的子類
發送 GET 請求的步驟很是簡單,只須要兩步就能夠完成:
使用 NSURLSession 對象建立 Task
執行 Task
//肯定請求路徑 NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520&pwd=520&type=JSON"]; //建立 NSURLSession 對象 NSURLSession *session = [NSURLSession sharedSession]; /** 根據對象建立 Task 請求 url 方法內部會自動將 URL 包裝成一個請求對象(默認是 GET 請求) completionHandler 完成以後的回調(成功或失敗) param data 返回的數據(響應體) param response 響應頭 param error 錯誤信息 */ NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler: ^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { //解析服務器返回的數據 NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); //默認在子線程中解析數據 NSLog(@"%@", [NSThread currentThread]); }]; //發送請求(執行Task) [dataTask resume];
發送 POST 請求的步驟與發送 GET 請求同樣:
使用 NSURLSession 對象建立 Task
執行 Task
//肯定請求路徑 NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"]; //建立可變請求對象 NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url]; //修改請求方法 requestM.HTTPMethod = @"POST"; //設置請求體 requestM.HTTPBody = [@"username=520&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding]; //建立會話對象 NSURLSession *session = [NSURLSession sharedSession]; //建立請求 Task NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:requestM completionHandler: ^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { //解析返回的數據 NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]); }]; //發送請求 [dataTask resume];
建立 NSURLSession 對象設置代理
使用 NSURLSession 對象建立 Task
執行 Task
//肯定請求路徑 NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"]; //建立可變請求對象 NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url]; //設置請求方法 requestM.HTTPMethod = @"POST"; //設置請求體 requestM.HTTPBody = [@"username=520&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding]; //建立會話對象,設置代理 /** 第一個參數:配置信息 第二個參數:設置代理 第三個參數:隊列,若是該參數傳遞nil 那麼默認在子線程中執行 */ NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:nil]; //建立請求 Task NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:requestM]; //發送請求 [dataTask resume];
遵照協議,實現代理方法(經常使用的有三種代理方法)
-(void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler { //子線程中執行 NSLog(@"接收到服務器響應的時候調用 -- %@", [NSThread currentThread]); self.dataM = [NSMutableData data]; //默認狀況下不接收數據 //必須告訴系統是否接收服務器返回的數據 completionHandler(NSURLSessionResponseAllow); } -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { NSLog(@"接受到服務器返回數據的時候調用,可能被調用屢次"); //拼接服務器返回的數據 [self.dataM appendData:data]; } -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { NSLog(@"請求完成或者是失敗的時候調用"); //解析服務器返回數據 NSLog(@"%@", [[NSString alloc] initWithData:self.dataM encoding:NSUTF8StringEncoding]); }
NSURLSession 對象在使用的時候,若是設置了代理,那麼 session 會對代理對象保持一個強引用,在合適的時候應該主動進行釋放
能夠在控制器調用 viewDidDisappear 方法的時候來進行處理,能夠經過調用 invalidateAndCancel 方法或者是 finishTasksAndInvalidate 方法來釋放對代理對象的強引用
invalidateAndCancel 方法直接取消請求而後釋放代理對象
finishTasksAndInvalidate 方法等請求完成以後釋放代理對象。
[self.session finishTasksAndInvalidate];
在前面請求數據的時候就至關於一個簡單的下載過程,NSURLSessionDataTask 下載文件具體的步驟與上相似:
使用 NSURLSession 對象建立一個 Task 請求
執行請求
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString: @"http://120.25.226.186:32812/resources/images/minion_01.png"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { //解析數據 UIImage *image = [UIImage imageWithData:data]; //回到主線程設置圖片 dispatch_async(dispatch_get_main_queue(), ^{ self.imageView.image = image; }); }] resume];
使用 NSURLSession 對象建立下載請求
在下載請求中移動文件到指定位置
執行請求
//肯定請求路徑 NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"]; //建立請求對象 NSURLRequest *request = [NSURLRequest requestWithURL:url]; //建立會話對象 NSURLSession *session = [NSURLSession sharedSession]; //建立會話請求 //優勢:該方法內部已經完成了邊接收數據邊寫沙盒的操做,解決了內存飆升的問題 NSURLSessionDownloadTask *downTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { //默認存儲到臨時文件夾 tmp 中,須要剪切文件到 cache NSLog(@"%@", location);//目標位置 NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename]; /** fileURLWithPath:有協議頭 URLWithString:無協議頭 */ [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil]; }]; //發送請求 [downTask resume];
以上方法沒法監聽下載進度,如要獲取下載進度,可使用代理的方式進行下載。
NSURLSessionDataTask
下載文件能夠實現離線斷點下載,可是代碼相對複雜
NSURLSessionDownloadTask
下載文件能夠實現斷點下載,但不能離線斷點下載
內部已經完成了邊接收數據邊寫入沙盒的操做
解決了下載大文件時的內存飆升問題
關於使用 NSURLSession 進行上傳文件操做,我只想說真的很麻煩,建議你們時間充沛且有興趣的能夠研究一下,若是不想研究也是能夠的,繼續使用咱們偉大的 AFN 框架就好。至於 AFN 框架的使用,這裏就不贅述了,後期若是有時間會更新一些經常使用的 AFN 使用方法,敬請期待。
附:使用 NSURLSession 上傳文件主要步驟及注意點
主要步驟:
肯定上傳請求的路徑( NSURL )
建立可變的請求對象( NSMutableURLRequest )
修改請求方法爲 POST
設置請求頭信息(告知服務器端這是一個文件上傳請求)
按照固定的格式拼接要上傳的文件等參數
根據請求對象建立會話對象( NSURLSession 對象)
根據 session 對象來建立一個 uploadTask 上傳請求任務
執行該上傳請求任務(調用 resume 方法)
獲得服務器返回的數據,解析數據(上傳成功 | 上傳失敗)
注意點:
建立可變的請求對象,由於須要修改請求方法爲 POST,設置請求頭信息
設置請求頭這個步驟可能會被遺漏
要處理上傳參數的時候,必定要按照固定的格式來進行拼接
須要採用合適的方法來得到上傳文件的二進制數據類型( MIMEType,獲取方式以下)
對着該文件發送一個網絡請求,接收到該請求響應的時候,能夠經過響應頭信息中的 MIMEType 屬性獲得
使用通用的二進制數據類型表示任意的二進制數據 application/octet-stream
調用 C 語言的 API 來獲取
[self mimeTypeForFileAtPath:@"此處爲上傳文件的路徑"]
原文:http://www.jianshu.com/p/b0ddadd34037