iOS開發網絡篇—NSURLConnection基本使用
一、NSURLConnection的常用類
(1)NSURL:請求地址
(2)NSURLRequest:封裝一個請求,保存發給服務器的全部數據,包括一個NSURL對象,請求方法、請求頭、請求體....
(3)NSMutableURLRequest:NSURLRequest的子類
(4)NSURLConnection:負責發送請求,建立客戶端和服務器的連接。發送NSURLRequest的數據給服務器,并收集來自服務器的響應數據
?
使用NSURLConnection發送請求的步驟很簡單
(1)創建一個NSURL對象,設置請求路徑(設置請求路徑)
(2)傳入NSURL創建一個NSURLRequest對象,設置請求頭和請求體(創建請求對象)
(3)使用NSURLConnection發送NSURLRequest(發送請求)
2.代碼示例
(1)發送請求的三個步驟:
// // YYViewController.m // 01-NSURLConnection的使用(GET) // // Created by apple on 14-6-28. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" #import "MBProgressHUD+MJ.h"@interface YYViewController () @property (weak, nonatomic) IBOutlet UITextField *username; @property (weak, nonatomic) IBOutlet UITextField *pwd; - (IBAction)login;@end@implementation YYViewController- (IBAction)login { // 1.提前的表單驗證if (self.username.text.length==0) {[MBProgressHUD showError:@"請輸入用戶名"];return;}if (self.pwd.text.length==0) {[MBProgressHUD showError:@"請輸入密碼"];return;} // 2.發送請求給服務器(帶上賬號和密碼)//添加一個遮罩,禁止用戶操作 // [MBProgressHUD showMessage:@"正在努力加載中...."]; // GET請求:請求行\請求頭\請求體 // // 1.設置請求路徑NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];NSURL *url=[NSURL URLWithString:urlStr]; // 2.創建請求對象NSURLRequest *request=[NSURLRequest requestWithURL:url]; // 3.發送請求//發送同步請求,在主線程執行NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];//(一直在等待服務器返回數據,這行代碼會卡住,如果服務器沒有返回數據,那么在主線程UI會卡住不能繼續執行操作)NSLog(@"--%d--",data.length); } @end
模擬器情況:
?
打印服務器返回的信息:
?
// // YYViewController.m // 01-NSURLConnection的使用(GET) // // Created by apple on 14-6-28. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" #import "MBProgressHUD+MJ.h"@interface YYViewController () @property (weak, nonatomic) IBOutlet UITextField *username; @property (weak, nonatomic) IBOutlet UITextField *pwd; - (IBAction)login;@end@implementation YYViewController- (IBAction)login { // 1.提前的表單驗證if (self.username.text.length==0) {[MBProgressHUD showError:@"請輸入用戶名"];return;}if (self.pwd.text.length==0) {[MBProgressHUD showError:@"請輸入密碼"];return;} // 2.發送請求給服務器(帶上賬號和密碼)//添加一個遮罩,禁止用戶操作[MBProgressHUD showMessage:@"正在努力加載中...."];// // 1.設置請求路徑NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];NSURL *url=[NSURL URLWithString:urlStr];// 2.創建請求對象NSURLRequest *request=[NSURLRequest requestWithURL:url];// 3.發送請求//3.1發送同步請求,在主線程執行 // NSData *data=[NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];//(一直在等待服務器返回數據,這行代碼會卡住,如果服務器沒有返回數據,那么在主線程UI會卡住不能繼續執行操作)//3.1發送異步請求//創建一個隊列(默認添加到該隊列中的任務異步執行) // NSOperationQueue *queue=[[NSOperationQueue alloc]init];//獲取一個主隊列NSOperationQueue *queue=[NSOperationQueue mainQueue];[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {NSLog(@"--block回調數據--%@---%d", [NSThread currentThread],data.length);//隱藏HUD,刷新UI的操作一定要放在主線程執行 [MBProgressHUD hideHUD];//解析data/*{"success":"登錄成功"}{"error":"用戶名不存在"}{"error":"密碼不正確"}*/NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];NSLog(@"%@",dict);//判斷后,在界面提示登錄信息NSString *error=dict[@"error"];if (error) {[MBProgressHUD showError:error];}else{NSString *success=dict[@"success"];[MBProgressHUD showSuccess:success];}}];NSLog(@"請求發送完畢"); } @end
模擬器情況(注意這里使用了第三方框架):
?
打印查看:
?
NSOperationQueue *queue=[NSOperationQueue mainQueue];[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {//當請求結束的時候調用(有兩種結果,一個是成功拿到數據,也可能沒有拿到數據,請求失敗)NSLog(@"--block回調數據--%@---%d", [NSThread currentThread],data.length);//隱藏HUD,刷新UI的操作一定要放在主線程執行 [MBProgressHUD hideHUD];//解析data/*{"success":"登錄成功"}{"error":"用戶名不存在"}{"error":"密碼不正確"}*/if (data) {//請求成功NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];NSLog(@"%@",dict);//判斷后,在界面提示登錄信息NSString *error=dict[@"error"];if (error) {[MBProgressHUD showError:error];}else{NSString *success=dict[@"success"];[MBProgressHUD showSuccess:success];}}else //請求失敗 {[MBProgressHUD showError:@"網絡繁忙,請稍后重試!"];}}];
解析data
//解析data/*{"success":"登錄成功"}{"error":"用戶名不存在"}{"error":"密碼不正確"}*/
要監聽服務器返回的data,所以使用<NSURLConnectionDataDelegate>協議
常見大代理方法如下:
#pragma mark- NSURLConnectionDataDelegate代理方法//當接收到服務器的響應(連通了服務器)時會調用-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response//當接收到服務器的數據時會調用(可能會被調用多次,每次只傳遞部分數據)-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data//當服務器的數據加載完畢時就會調用-(void)connectionDidFinishLoading:(NSURLConnection *)connection//請求錯誤(失敗)的時候調用(請求超時\斷網\沒有網\,一般指客戶端錯誤)-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
使用異步方法發送get請求的代碼示例:
?
// // YYViewController.m // 01-NSURLConnection的使用(GET) // // Created by apple on 14-6-28. // Copyright (c) 2014年 itcase. All rights reserved. // #import "YYViewController.h" #import "MBProgressHUD+MJ.h"@interface YYViewController ()<NSURLConnectionDataDelegate> @property (weak, nonatomic) IBOutlet UITextField *username; @property (weak, nonatomic) IBOutlet UITextField *pwd; @property(nonatomic,strong)NSMutableData *responseData; - (IBAction)login;@end@implementation YYViewController- (IBAction)login { // 1.提前的表單驗證if (self.username.text.length==0) {[MBProgressHUD showError:@"請輸入用戶名"];return;}if (self.pwd.text.length==0) {[MBProgressHUD showError:@"請輸入密碼"];return;} // 2.發送請求給服務器(帶上賬號和密碼)//添加一個遮罩,禁止用戶操作[MBProgressHUD showMessage:@"正在努力加載中...."];// // 2.1設置請求路徑NSString *urlStr=[NSString stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];NSURL *url=[NSURL URLWithString:urlStr];// 2.2創建請求對象 // NSURLRequest *request=[NSURLRequest requestWithURL:url];//默認就是GET請求//設置請求超時NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];request.timeoutInterval=5.0;// 2.3.發送請求//使用代理發送異步請求(通常應用于文件下載)NSURLConnection *conn=[NSURLConnection connectionWithRequest:request delegate:self];[conn start];NSLog(@"已經發出請求---"); }#pragma mark- NSURLConnectionDataDelegate代理方法 /**當接收到服務器的響應(連通了服務器)時會調用*/ -(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {NSLog(@"接收到服務器的響應");//初始化數據self.responseData=[NSMutableData data]; }/* *當接收到服務器的數據時會調用(可能會被調用多次,每次只傳遞部分數據) */ -(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {NSLog(@"接收到服務器的數據");//拼接數據 [self.responseData appendData:data];NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]); }/**當服務器的數據加載完畢時就會調用*/ -(void)connectionDidFinishLoading:(NSURLConnection *)connection {NSLog(@"服務器的數據加載完畢");//隱藏HUD [MBProgressHUD hideHUD];//處理服務器返回的所有數據NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:nil];//判斷后,在界面提示登錄信息NSString *error=dict[@"error"];if (error) {[MBProgressHUD showError:error];}else{NSString *success=dict[@"success"];[MBProgressHUD showSuccess:success];}NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]); } /**請求錯誤(失敗)的時候調用(請求超時\斷網\沒有網\,一般指客戶端錯誤)*/ -(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { // NSLog(@"請求錯誤");//隱藏HUD [MBProgressHUD hideHUD];[MBProgressHUD showError:@"網絡繁忙,請稍后重試!"]; } @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;