iOS開發網絡篇—NSURLConnection基本使用


最新博文發布地址 花田半畝http://wendingding.com/

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.發送請求給服務器(帶上賬號和密碼)
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 @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

模擬器情況(注意這里使用了第三方框架):

打印查看:

代碼說明:
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             }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;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM