iOS開發網路篇—NSURLConnection基本使用,iosnsurlconnection
iOS開發網路篇—NSURLConnection基本使用
一、NSURLConnection的常用類
(1)NSURL:請求地址
(2)NSURLRequest:封裝一個請求,儲存發給伺服器的全部資料,包括一個NSURL對象,要求方法、要求標頭、請求體....
(3)NSMutableURLRequest:NSURLRequest的子類
(4)NSURLConnection:負責發送請求,建立用戶端和伺服器的串連。發送NSURLRequest的資料給伺服器,並收集來自伺服器的響應資料
二、NSURLConnection的使用1.簡單說明
使用NSURLConnection發送請求的步驟很簡單
(1)建立一個NSURL對象,佈建要求路徑(佈建要求路徑)
(2)傳入NSURL建立一個NSURLRequest對象,佈建要求頭和請求體(建立請求對象)
(3)使用NSURLConnection發送NSURLRequest(發送請求)
2.程式碼範例
(1)發送請求的三個步驟:
1.佈建要求路徑2.建立請求對象3.發送請求3.1發送同步請求(一直在等待伺服器返回資料,這行代碼會卡住,如果伺服器,沒有返回資料,那麼在主線程UI會卡住不能繼續執行操作)有傳回值3.2發送非同步請求:沒有傳回值說明:任何NSURLRequest預設都是get請求。 (2)發送同步請求程式碼範例:
1 // 2 // YYViewController.m 3 // 01-NSURLConnection的使用(GET) 4 // 5 // Created by apple on 14-6-28. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYViewController.h"10 #import "MBProgressHUD+MJ.h"11 12 @interface YYViewController ()13 @property (weak, nonatomic) IBOutlet UITextField *username;14 @property (weak, nonatomic) IBOutlet UITextField *pwd;15 - (IBAction)login;16 17 @end18 19 @implementation YYViewController20 21 - (IBAction)login {22 // 1.提前的表單驗證23 if (self.username.text.length==0) {24 [MBProgressHUD showError:@"請輸入使用者名稱"];25 return;26 }27 if (self.pwd.text.length==0) {28 [MBProgressHUD showError:@"請輸入密碼"];29 return;30 }31 // 2.發送請求給伺服器(帶上帳號和密碼)32 //添加一個遮罩,禁止使用者操作33 // [MBProgressHUD showMessage:@"正在努力載入中...."];34 // GET請求:請求行\要求標頭\請求體35 //36 // 1.佈建要求路徑37 NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];38 NSURL *url=[NSURL URLWithString:urlStr];39 // 2.建立請求對象40 NSURLRequest *request=[NSURLRequest requestWithURL:url];41 // 3.發送請求42 //發送同步請求,在主線程執行43 NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];44 //(一直在等待伺服器返回資料,這行代碼會卡住,如果伺服器沒有返回資料,那麼在主線程UI會卡住不能繼續執行操作)45 NSLog(@"--%d--",data.length);46 }47 @end
模擬器情況:
列印伺服器返回的資訊:
補充說明:1.提前的表單驗證2.發送請求給伺服器(帶上帳號和密碼)GET請求:請求行\要求標頭\請求體注意:GET請求中不存在請求體,因為所有的資訊都寫在URL裡面。在IOS裡面,請求行和要求標頭都不用寫。 (3)發送非同步請求發送非同步請求有兩種方式:1)使用block回調2)代理
A.使用block回調方法發送非同步請求使用block回調程式碼範例:
1 // 2 // YYViewController.m 3 // 01-NSURLConnection的使用(GET) 4 // 5 // Created by apple on 14-6-28. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYViewController.h"10 #import "MBProgressHUD+MJ.h"11 12 @interface YYViewController ()13 @property (weak, nonatomic) IBOutlet UITextField *username;14 @property (weak, nonatomic) IBOutlet UITextField *pwd;15 - (IBAction)login;16 17 @end18 19 @implementation YYViewController20 21 - (IBAction)login {22 // 1.提前的表單驗證23 if (self.username.text.length==0) {24 [MBProgressHUD showError:@"請輸入使用者名稱"];25 return;26 }27 if (self.pwd.text.length==0) {28 [MBProgressHUD showError:@"請輸入密碼"];29 return;30 }31 // 2.發送請求給伺服器(帶上帳號和密碼)32 //添加一個遮罩,禁止使用者操作33 [MBProgressHUD showMessage:@"正在努力載入中...."];34 35 //36 // 1.佈建要求路徑37 NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];38 NSURL *url=[NSURL URLWithString:urlStr];39 40 // 2.建立請求對象41 NSURLRequest *request=[NSURLRequest requestWithURL:url];42 43 // 3.發送請求44 //3.1發送同步請求,在主線程執行45 // NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];46 //(一直在等待伺服器返回資料,這行代碼會卡住,如果伺服器沒有返回資料,那麼在主線程UI會卡住不能繼續執行操作)47 48 //3.1發送非同步請求49 //建立一個隊列(預設添加到該隊列中的任務非同步執行)50 // NSOperationQueue *queue=[[NSOperationQueue alloc]init];51 //擷取一個主隊列52 NSOperationQueue *queue=[NSOperationQueue mainQueue];53 [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {54 NSLog(@"--block回調資料--%@---%d", [NSThread currentThread],data.length);55 //隱藏HUD,重新整理UI的操作一定要放在主線程執行56 [MBProgressHUD hideHUD];57 58 //解析data59 /*60 {"success":"登入成功"}61 {"error":"使用者名稱不存在"}62 {"error":"密碼不正確"}63 */64 NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];65 NSLog(@"%@",dict);66 67 //判斷後,在介面提示登入資訊68 NSString *error=dict[@"error"];69 if (error) {70 [MBProgressHUD showError:error];71 }else72 {73 NSString *success=dict[@"success"];74 [MBProgressHUD showSuccess:success];75 }76 }];77 NSLog(@"請求發送完畢");78 }79 @end
模擬器情況(注意這裡使用了第三方架構):
列印查看:
代碼說明:block程式碼片段:當伺服器有返回資料的時候調用會開一條新的線程去發送請求,主線程繼續往下走,當拿到伺服器的返回資料的資料的時候再回調block,執行block程式碼片段。這種情況不會卡住主線程。隊列的作用:決定這個block操作放在哪個線程執行?重新整理UI介面的操作應該放在主線程執行,不能放在子線程,在子線程處理UI相關操作會出現一些莫名的問題。提示:(1)建立一個操作,放在NSOperation隊列中執行,預設是非同步執行的。(2)mainqueue 返回一個和主線程相關的隊列,即主隊列。 新的問題:如果向伺服器發送請求,卻並沒有拿到資料,那麼程式會崩潰(data不可為空)改進代碼:
1 NSOperationQueue *queue=[NSOperationQueue mainQueue]; 2 [NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) { 3 //當請求結束的時候調用(有兩種結果,一個是成功拿到資料,也可能沒有拿到資料,請求失敗) 4 NSLog(@"--block回調資料--%@---%d", [NSThread currentThread],data.length); 5 //隱藏HUD,重新整理UI的操作一定要放在主線程執行 6 [MBProgressHUD hideHUD]; 7 8 //解析data 9 /*10 {"success":"登入成功"}11 {"error":"使用者名稱不存在"}12 {"error":"密碼不正確"}13 */14 if (data) {//請求成功15 NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];16 NSLog(@"%@",dict);17 18 //判斷後,在介面提示登入資訊19 NSString *error=dict[@"error"];20 if (error) {21 [MBProgressHUD showError:error];22 }else23 {24 NSString *success=dict[@"success"];25 [MBProgressHUD showSuccess:success];26 }27 }else //請求失敗28 {29 [MBProgressHUD showError:@"網路繁忙,請稍後重試!"];30 }31 32 }];
解析data
//解析data /* {"success":"登入成功"} {"error":"使用者名稱不存在"} {"error":"密碼不正確"} */
說明:使用NSJSONSerialization 返回的對象,取決於最外層是什麼,如果是{}那就是字典,[]那就是數組等。補充說明:首先確定請求路徑,然後建立請求對象(預設發送的時get請求),使用非同步方法呼叫(一調用這個方法,它會自動開啟一個子線程去發送請求,當請求成功,資料返回的時候自動調用內部的程式碼片段,這個程式碼片段在那個線程執行取決於隊列,如果是主隊列,那麼在子線程發送請求成功拿到伺服器的資料後,回到主線程中解析資料,重新整理UI介面)。
B.使用代理方法發送非同步請求
要監聽伺服器返回的data,所以使用<NSURLConnectionDataDelegate>協議
常見大代理方法如下:
1 #pragma mark- NSURLConnectionDataDelegate代理方法 2 3 //當接收到伺服器的響應(連通了伺服器)時會調用 4 5 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 6 7 //當接收到伺服器的資料時會調用(可能會被調用多次,每次只傳遞部分資料) 8 9 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data10 11 //當伺服器的資料載入完畢時就會調用12 13 -(void)connectionDidFinishLoading:(NSURLConnection *)connection14 15 //請求錯誤(失敗)的時候調用(請求逾時\斷網\沒有網\,一般指用戶端錯誤)16 17 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
使用非同步方法呼叫發送get請求的程式碼範例:
1 // 2 // YYViewController.m 3 // 01-NSURLConnection的使用(GET) 4 // 5 // Created by apple on 14-6-28. 6 // Copyright (c) 2014年 itcase. All rights reserved. 7 // 8 9 #import "YYViewController.h" 10 #import "MBProgressHUD+MJ.h" 11 12 @interface YYViewController ()<NSURLConnectionDataDelegate> 13 @property (weak, nonatomic) IBOutlet UITextField *username; 14 @property (weak, nonatomic) IBOutlet UITextField *pwd; 15 @property(nonatomic,strong)NSMutableData *responseData; 16 - (IBAction)login; 17 18 @end 19 20 @implementation YYViewController 21 22 - (IBAction)login { 23 // 1.提前的表單驗證 24 if (self.username.text.length==0) { 25 [MBProgressHUD showError:@"請輸入使用者名稱"]; 26 return; 27 } 28 if (self.pwd.text.length==0) { 29 [MBProgressHUD showError:@"請輸入密碼"]; 30 return; 31 } 32 // 2.發送請求給伺服器(帶上帳號和密碼) 33 //添加一個遮罩,禁止使用者操作 34 [MBProgressHUD showMessage:@"正在努力載入中...."]; 35 36 // 37 // 2.1佈建要求路徑 38 NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text]; 39 NSURL *url=[NSURL URLWithString:urlStr]; 40 41 // 2.2建立請求對象 42 // NSURLRequest *request=[NSURLRequest requestWithURL:url];//預設就是GET請求 43 //佈建要求逾時 44 NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url]; 45 request.timeoutInterval=5.0; 46 47 // 2.3.發送請求 48 //使用代理髮送非同步請求(通常應用於檔案下載) 49 NSURLConnection *conn=[NSURLConnection connectionWithRequest:request delegate:self]; 50 [conn start]; 51 NSLog(@"已經發出請求---"); 52 } 53 54 #pragma mark- NSURLConnectionDataDelegate代理方法 55 /* 56 *當接收到伺服器的響應(連通了伺服器)時會調用 57 */ 58 -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 59 { 60 NSLog(@"接收到伺服器的響應"); 61 //初始化資料 62 self.responseData=[NSMutableData data]; 63 } 64 65 /* 66 *當接收到伺服器的資料時會調用(可能會被調用多次,每次只傳遞部分資料) 67 */ 68 -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 69 { 70 NSLog(@"接收到伺服器的資料"); 71 //拼接資料 72 [self.responseData appendData:data]; 73 NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]); 74 } 75 76 /* 77 *當伺服器的資料載入完畢時就會調用 78 */ 79 -(void)connectionDidFinishLoading:(NSURLConnection *)connection 80 { 81 NSLog(@"伺服器的資料載入完畢"); 82 //隱藏HUD 83 [MBProgressHUD hideHUD]; 84 85 //處理伺服器返回的所有資料 86 NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:nil]; 87 88 //判斷後,在介面提示登入資訊 89 NSString *error=dict[@"error"]; 90 if (error) { 91 [MBProgressHUD showError:error]; 92 }else 93 { 94 NSString *success=dict[@"success"]; 95 [MBProgressHUD showSuccess:success]; 96 } 97 NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]); 98 } 99 /*100 *請求錯誤(失敗)的時候調用(請求逾時\斷網\沒有網\,一般指用戶端錯誤)101 */102 -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error103 {104 // NSLog(@"請求錯誤");105 //隱藏HUD106 [MBProgressHUD hideHUD];107 [MBProgressHUD showError:@"網路繁忙,請稍後重試!"];108 }109 @end
列印查看:
補充:
(1)資料的處理
在didReceiveData:方法中,拼接接收到的所有資料,等所有資料都拿到後,在connectionDidFinishLoading:方法中進行處理
(2)網路延遲
在做網路開發的時候,一定要考慮到網路延遲情況的處理,可以在伺服器的代碼設定一個斷點類比。
在伺服器代碼的登入方法中設定斷點
佈建要求的最大延遲
模擬器情況:
列印查看:
三、NSMutableURLRequest
NSMutableURLRequest是NSURLRequest的子類,常用方法有
佈建要求逾時等待時間(超過這個時間就算逾時,請求失敗)- (void)setTimeoutInterval:(NSTimeInterval)seconds;
佈建要求方法(比如GET和POST)- (void)setHTTPMethod:(NSString *)method;
佈建要求體- (void)setHTTPBody:(NSData *)data;
佈建要求頭- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;