NSURLConnection,在iOS 9被宣布棄用,本文不使用NSURLConnection進行網絡編程,有興趣的童鞋可以參考:
iOS開發 GET、POST請求方法(NSURLConnection篇)
介紹:NSURLSession,為iOS7中的新網絡接口,是在2013年的WWDC上,由Apple提出的NSURLConnection繼任者的:NSURLSession。
NSURLSession,與NSURLConnection是並列的,且可以支持後台相關的網絡操作的新特性;與NSURLConnection不同的是,NSURLSession把NSURLConnection替換成NSURLSession, NSURLSessionConfiguration,NSURLSessionTask。
NSURLSession一般分別兩部操作:第一,通過NSURLSession的實例創建task;第二,執行task;
而NSURLSessionTask,也就是task,可以把它當作所謂的任務。
NSURLSessionTask是一個抽象子類,它有三個具體的子類是可以直接使用的:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask。這三個類應用的三個基本網絡任務:獲取數據、上傳文件、下載文件。與數據有關的NSURLSessionDataTask也可以勝任上傳下載的任務,所以經常使用到。
————示例————–
一、GET方法
// 1.創建一個網絡路徑 NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://172.16.2.254/php/phonelogin?yourname=%@&yourpas=%@&btn=login",yourname,yourpass]]; // 2.創建一個網絡請求 NSURLRequest *request =[NSURLRequest requestWithURL:url]; // 3.獲得會話對象 NSURLSession *session = [NSURLSession sharedSession]; // 4.根據會話對象,創建一個Task任務: NSURLSessionDataTask *sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"從服務器獲取到數據"); /* 對從服務器獲取到的數據data進行相應的處理: */ NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingMutableLeaves) error:nil]; }]; // 5.最後一步,執行任務(resume也是繼續執行): [sessionDataTask resume];
二、POST方法
// 1.創建一個網絡路徑 NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://172.16.2.254/php/phonelogin"]]; // 2.創建一個網絡請求,分別設置請求方法、請求參數 NSMutableURLRequest *request =[NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST"; NSString *args = [NSString stringWithFormat:@"yourname=%@&yourpass=%@&btn=login",yourname,yourpass]; request.HTTPBody = [args dataUsingEncoding:NSUTF8StringEncoding]; // 3.獲得會話對象 NSURLSession *session = [NSURLSession sharedSession]; // 4.根據會話對象,創建一個Task任務 NSURLSessionDataTask *sessionDataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSLog(@"從服務器獲取到數據"); /* 對從服務器獲取到的數據data進行相應的處理. */ NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingMutableLeaves) error:nil]; }]; //5.最後一步,執行任務,(resume也是繼續執行)。 [sessionDataTask resume];
三、NSURLSessionDataDelegate代理方法
從前面兩種方法中,我們都可以看出,相比NSURLConnection,NSURLSession提供了block方式處理返回數據的簡便方式,但是,如果項目需要在網絡請求數據的過程中,要做進一步的處理的話,需要調用NSURLSession的代理方法。
通常,使用代理方法需要先設置代理對象,但是通過查看NSURLSessionDataDelegate文檔,我們可以看到如下,代理屬性delegate為只讀狀態。
@property (nullable, readonly, retain) id delegate;
那麼我們需要怎樣設置代理對象呢?下面我們通過代碼演示關於代理方法的使用:
首先在文件開頭添加代理協議,
#import @interface ViewController : UIViewController //遵循代理協議 @end
主方法的編寫如下:
// 1.delegateQueue參數表示協議方法將會在(NSOperationQueue)隊列裡面執行。(session的delegate屬性是只讀的,所以使用如下方法設置代理。) NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]]; // 2.創建任務(因為要使用代理方法,就不需要block方式的初始化了) NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://172.16.2.254/php/phonelogin?yourname=%@&yourpass=%@&btn=login",yourname,yourpass]]; NSURLSessionDataTask *task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:url]]; // 3.執行任務 [task resume];
關於代理行為:
#pragma mark -- NSURLSessionDataDelegate// 1.接收到服務器的響應 - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler { //【注意:此處需要允許處理服務器的響應,才會繼續加載服務器的數據。 若在接收響應時需要對返回的參數進行處理(如獲取響應頭信息等),那麼這些處理應該放在這個允許操作的前面。】 completionHandler(NSURLSessionResponseAllow); } // 2.接收到服務器的數據(此方法在接收數據過程會多次調用) - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data { // 處理每次接收的數據,例如每次拼接到自己創建的數據receiveData [self.receiveData appendData:data]; } // 3.3.任務完成時調用(如果成功,error == nil) - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if(error == nil){ /* 請求完成,成功或者失敗的處理 */ } else{ NSLog(@"請求失敗:%@",error); } }
四、NSURLSessionDownloadTask
1.NSURLSessionDownloadTask:文件下載任務
// 1.創建網路路徑 NSURL *url = [NSURL URLWithString:@"http://172.16.2.254/php/phonelogin/image.png"] ; // 2.獲取會話 NSURLSession *session = [NSURLSession sharedSession]; // 3.根據會話,創建任務 NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) { /* a.location是沙盒中tmp文件夾下的一個臨時url,文件下載後會存到這個位置,由於tmp中的文件隨時可能被刪除,所以我們需要自己需要把下載的文件移動到其他地方:pathUrl. b.response.suggestedFilename是從相應中取出文件在服務器上存儲路徑的最後部分,例如根據本路徑為,最後部分應該為:“image.png” */ NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename]; NSURL *pathUrl = [NSURL fileURLWithPath:path]; // 剪切文件 [[NSFileManager defaultManager] moveItemAtURL:location toURL:pathUrl error:nil]; }]; // 4.啟動任務 [task resume];
2.NSURLSessionDownloadDelegate代理方法:
首先添加協議
#import @interface ViewController : UIViewController //遵循代理協議 @end
代理方法如下:
// 1.每次寫入調用(會調用多次) - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { // 可在這裡通過已寫入的長度和總長度算出下載進度 CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite; NSLog(@"%f",progress); } // 2.下載完成時調用 - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { // 這裡的location也是一個臨時路徑,需要自己移動到需要的路徑(caches下面) NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename]; [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil]; } // 3.請求成功/失敗(如果成功,error為nil) - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error { if(error == nil){ /* 請求完成,成功或者失敗的處理 */ } else{ NSLog(@"請求失敗:%@",error); } }
五、NSURLSessionUploadTask
1. NSURLSessionUploadTask上傳文件的方式有2種:
GET方法:
NSURLSessionUploadTask *task =[[NSURLSession sharedSession] uploadTaskWithRequest:request fromFile:fileName completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {}];
POST方法:
[[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:body completionHandler:^(NSData data, NSURLResponse response, NSError *error) { NSLog(@"-------%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]); }];
不同的點,在於,用post方法需要添加網絡路徑的請求體body,而在實際開發中,上傳文件一般使用post方式,更加安全可靠。
其他:
當然,對於使用NSURLSession開發的項目來說,還有更多的方式可以執行,需要我們在日常開發過程多多發現,以便更好地使用這個較新的網絡接口,例如AFNetWorking2.0版本之後,就有了基於NSURLSession的封裝運用,具體的有興趣的童鞋可以去github了解下。
本文作者:伯樂在線 - 啊左~