NSURLConnection,在iOS9被宣佈棄用,本文不使用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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// 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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
// 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為只讀狀態。
1 |
@property (nullable, readonly, retain) id delegate; |
那麼我們需要怎樣設定代理物件呢?下面我們通過程式碼演示關於代理方法的使用:
首先在檔案開頭新增代理協議,
1 2 3 4 5 |
#import @interface ViewController : UIViewController //遵循代理協議 @end |
主方法的編寫如下:
1 2 3 4 5 6 7 8 9 10 11 |
// 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]; |
關於代理行為:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
#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 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
// 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代理方法:
首先新增協議
1 2 3 4 5 |
#import @interface ViewController : UIViewController //遵循代理協議 @end |
代理方法如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
// 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方法:
1 2 3 |
NSURLSessionUploadTask *task =[[NSURLSession sharedSession] uploadTaskWithRequest:request fromFile:fileName completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { }]; |
POST方法:
1 2 3 4 |
[[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瞭解下。
打賞支援我寫出更多好文章,謝謝!
打賞作者
打賞支援我寫出更多好文章,謝謝!
任選一種支付方式