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 @end
18
19 @implementation YYViewController
20
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 // 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 ()
13 @property (weak, nonatomic) IBOutlet UITextField *username;
14 @property (weak, nonatomic) IBOutlet UITextField *pwd;
15 - (IBAction)login;
16
17 @end
18
19 @implementation YYViewController
20
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 //解析data
59 /*
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 }else
72 {
73 NSString *success=dict[@"success"];
74 [MBProgressHUD showSuccess:success];
75 }
76 }];
77 NSLog(@"請求發送完畢");
78 }
79 @end
模擬器情況(注意這裡使用了第三方框架):

打印查看:

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 }else
23 {
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 *)data 10 11 //當服務器的數據加載完畢時就會調用 12 13 -(void)connectionDidFinishLoading:(NSURLConnection *)connection 14 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 *)error
103 {
104 // NSLog(@"請求錯誤");
105 //隱藏HUD
106 [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;