NSURLConnection案例

iOS開發(fā)網(wǎng)絡(luò)篇—NSURLConnection基本使用

一、NSURLConnection的常用類

(1)NSURL:請(qǐng)求地址

(2)NSURLRequest:封裝一個(gè)請(qǐng)求,保存發(fā)給服務(wù)器的全部數(shù)據(jù),包括一個(gè)NSURL對(duì)象,請(qǐng)求方法、請(qǐng)求頭、請(qǐng)求體....

(3)NSMutableURLRequest:NSURLRequest的子類

(4)NSURLConnection:負(fù)責(zé)發(fā)送請(qǐng)求,建立客戶端和服務(wù)器的連接。發(fā)送NSURLRequest的數(shù)據(jù)給服務(wù)器,并收集來自服務(wù)器的響應(yīng)數(shù)據(jù)

二、NSURLConnection的使用

1.簡(jiǎn)單說明

使用NSURLConnection發(fā)送請(qǐng)求的步驟很簡(jiǎn)單

(1)創(chuàng)建一個(gè)NSURL對(duì)象,設(shè)置請(qǐng)求路徑(設(shè)置請(qǐng)求路徑)

(2)傳入NSURL創(chuàng)建一個(gè)NSURLRequest對(duì)象,設(shè)置請(qǐng)求頭和請(qǐng)求體(創(chuàng)建請(qǐng)求對(duì)象)

(3)使用NSURLConnection發(fā)送NSURLRequest(發(fā)送請(qǐng)求)


2.代碼示例

(1)發(fā)送請(qǐng)求的三個(gè)步驟:

1.設(shè)置請(qǐng)求路徑

2.創(chuàng)建請(qǐng)求對(duì)象

3.發(fā)送請(qǐng)求

3.1發(fā)送同步請(qǐng)求(一直在等待服務(wù)器返回?cái)?shù)據(jù),這行代碼會(huì)卡住,如果服務(wù)器,沒有返回?cái)?shù)據(jù),那么在主線程UI會(huì)卡住不能繼續(xù)執(zhí)行操作)有返回值

3.2發(fā)送異步請(qǐng)求:沒有返回值

說明:任何NSURLRequest默認(rèn)都是get請(qǐng)求。

(2)發(fā)送同步請(qǐng)求代碼示例:


9#import"YYViewController.h"

10#import"MBProgressHUD+MJ.h"

11

12@interfaceYYViewController?()

13@property?(weak,?nonatomic)?IBOutlet?UITextField?*username;

14@property?(weak,?nonatomic)?IBOutlet?UITextField?*pwd;

15-?(IBAction)login;

16

17@end

18

19@implementationYYViewController

20

21-?(IBAction)login?{

22//1.提前的表單驗(yàn)證

23if(self.username.text.length==0)?{

24[MBProgressHUD?showError:@"請(qǐng)輸入用戶名"];

25return;

26}

27if(self.pwd.text.length==0)?{

28[MBProgressHUD?showError:@"請(qǐng)輸入密碼"];

29return;

30}

31//2.發(fā)送請(qǐng)求給服務(wù)器(帶上賬號(hào)和密碼)

32//添加一個(gè)遮罩,禁止用戶操作

33//[MBProgressHUD?showMessage:@"正在努力加載中...."];

34//GET請(qǐng)求:請(qǐng)求行\(zhòng)請(qǐng)求頭\請(qǐng)求體

35//

36//1.設(shè)置請(qǐng)求路徑

37NSString?*urlStr=[NSString?stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];

38NSURL?*url=[NSURL?URLWithString:urlStr];

39//2.創(chuàng)建請(qǐng)求對(duì)象

40NSURLRequest?*request=[NSURLRequest?requestWithURL:url];

41//3.發(fā)送請(qǐng)求

42//發(fā)送同步請(qǐng)求,在主線程執(zhí)行

43NSData?*data=[NSURLConnection?sendSynchronousRequest:request?returningResponse:nil?error:nil];

44//(一直在等待服務(wù)器返回?cái)?shù)據(jù),這行代碼會(huì)卡住,如果服務(wù)器沒有返回?cái)?shù)據(jù),那么在主線程UI會(huì)卡住不能繼續(xù)執(zhí)行操作)

45NSLog(@"--%d--",data.length);

46}

47@end

模擬器情況:

打印服務(wù)器返回的信息:


補(bǔ)充說明:

1.提前的表單驗(yàn)證

2.發(fā)送請(qǐng)求給服務(wù)器(帶上賬號(hào)和密碼)

GET請(qǐng)求:請(qǐng)求行\(zhòng)請(qǐng)求頭\請(qǐng)求體

注意:GET請(qǐng)求中不存在請(qǐng)求體,因?yàn)樗械男畔⒍紝懺赨RL里面。在IOS里面,請(qǐng)求行和請(qǐng)求頭都不用寫。

(3)發(fā)送異步請(qǐng)求

發(fā)送異步請(qǐng)求有兩種方式:

1)使用block回調(diào)

2)代理

A.使用block回調(diào)方法發(fā)送異步請(qǐng)求

使用block回調(diào)代碼示例:7//

8

9#import"YYViewController.h"

10#import"MBProgressHUD+MJ.h"

11

12@interfaceYYViewController?()

13@property?(weak,?nonatomic)?IBOutlet?UITextField?*username;

14@property?(weak,?nonatomic)?IBOutlet?UITextField?*pwd;

15-?(IBAction)login;

16

17@end

18

19@implementationYYViewController

20

21-?(IBAction)login?{

22//1.提前的表單驗(yàn)證

23if(self.username.text.length==0)?{

24[MBProgressHUD?showError:@"請(qǐng)輸入用戶名"];

25return;

26}

27if(self.pwd.text.length==0)?{

28[MBProgressHUD?showError:@"請(qǐng)輸入密碼"];

29return;

30}

31//2.發(fā)送請(qǐng)求給服務(wù)器(帶上賬號(hào)和密碼)

32//添加一個(gè)遮罩,禁止用戶操作

33[MBProgressHUD?showMessage:@"正在努力加載中...."];

34

35//

36//1.設(shè)置請(qǐng)求路徑

37NSString?*urlStr=[NSString?stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];

38NSURL?*url=[NSURL?URLWithString:urlStr];

39

40//2.創(chuàng)建請(qǐng)求對(duì)象

41NSURLRequest?*request=[NSURLRequest?requestWithURL:url];

42

43//3.發(fā)送請(qǐng)求

44//3.1發(fā)送同步請(qǐng)求,在主線程執(zhí)行

45//NSData?*data=[NSURLConnection?sendSynchronousRequest:request?returningResponse:nil?error:nil];

46//(一直在等待服務(wù)器返回?cái)?shù)據(jù),這行代碼會(huì)卡住,如果服務(wù)器沒有返回?cái)?shù)據(jù),那么在主線程UI會(huì)卡住不能繼續(xù)執(zhí)行操作)

47

48//3.1發(fā)送異步請(qǐng)求

49//創(chuàng)建一個(gè)隊(duì)列(默認(rèn)添加到該隊(duì)列中的任務(wù)異步執(zhí)行)

50//NSOperationQueue?*queue=[[NSOperationQueue?alloc]init];

51//獲取一個(gè)主隊(duì)列

52NSOperationQueue?*queue=[NSOperationQueue?mainQueue];

53[NSURLConnection?sendAsynchronousRequest:request?queue:queue?completionHandler:^(NSURLResponse?*response,?NSData?*data,?NSError?*connectionError)?{

54NSLog(@"--block回調(diào)數(shù)據(jù)--%@---%d",?[NSThread?currentThread],data.length);

55//隱藏HUD,刷新UI的操作一定要放在主線程執(zhí)行

56[MBProgressHUD?hideHUD];

57

58//解析data

59/*

60{"success":"登錄成功"}

61{"error":"用戶名不存在"}

62{"error":"密碼不正確"}

63*/

64NSDictionary?*dict=[NSJSONSerialization?JSONObjectWithData:data?options:NSJSONReadingMutableLeaves?error:nil];

65NSLog(@"%@",dict);

66

67//判斷后,在界面提示登錄信息

68NSString?*error=dict[@"error"];

69if(error)?{

70[MBProgressHUD?showError:error];

71}else

72{

73NSString?*success=dict[@"success"];

74[MBProgressHUD?showSuccess:success];

75}

76}];

77NSLog(@"請(qǐng)求發(fā)送完畢");

78}

79@end

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


打印查看:


代碼說明:

block代碼段:當(dāng)服務(wù)器有返回?cái)?shù)據(jù)的時(shí)候調(diào)用會(huì)開一條新的線程去發(fā)送請(qǐng)求,主線程繼續(xù)往下走,當(dāng)拿到服務(wù)器的返回?cái)?shù)據(jù)的數(shù)據(jù)的時(shí)候再回調(diào)block,執(zhí)行block代碼段。這種情況不會(huì)卡住主線程。

隊(duì)列的作用:決定這個(gè)block操作放在哪個(gè)線程執(zhí)行?

刷新UI界面的操作應(yīng)該放在主線程執(zhí)行,不能放在子線程,在子線程處理UI相關(guān)操作會(huì)出現(xiàn)一些莫名的問題。

提示:

(1)創(chuàng)建一個(gè)操作,放在NSOperation隊(duì)列中執(zhí)行,默認(rèn)是異步執(zhí)行的。

(2)mainqueue?? 返回一個(gè)和主線程相關(guān)的隊(duì)列,即主隊(duì)列。

新的問題:如果向服務(wù)器發(fā)送請(qǐng)求,卻并沒有拿到數(shù)據(jù),那么程序會(huì)崩潰(data不能為空)

改進(jìn)代碼:

1NSOperationQueue *queue=[NSOperationQueue mainQueue];

2[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

3//當(dāng)請(qǐng)求結(jié)束的時(shí)候調(diào)用(有兩種結(jié)果,一個(gè)是成功拿到數(shù)據(jù),也可能沒有拿到數(shù)據(jù),請(qǐng)求失?。?/p>

4NSLog(@"--block回調(diào)數(shù)據(jù)--%@---%d", [NSThread currentThread],data.length);

5//隱藏HUD,刷新UI的操作一定要放在主線程執(zhí)行

6[MBProgressHUD hideHUD];

8//解析data

/*10{"success":"登錄成功"}

11{"error":"用戶名不存在"}

12{"error":"密碼不正確"}

13*/14if(data) {//請(qǐng)求成功

15NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];

NSLog(@"%@",dict);

18//判斷后,在界面提示登錄信息

NSString *error=dict[@"error"];

20if(error) {

21[MBProgressHUD showError:error];

22}else

{24NSString *success=dict[@"success"];

25[MBProgressHUD showSuccess:success];

}

27}else//請(qǐng)求失敗

28{

29[MBProgressHUD showError:@"網(wǎng)絡(luò)繁忙,請(qǐng)稍后重試!"];}}];

解析data

//解析data/*{"success":"登錄成功"}

{"error":"用戶名不存在"}

{"error":"密碼不正確"}*/

說明:使用NSJSONSerialization 返回的對(duì)象,取決于最外層是什么,如果是{}那就是字典,[]那就是數(shù)組等。

補(bǔ)充說明:

首先確定請(qǐng)求路徑,然后創(chuàng)建請(qǐng)求對(duì)象(默認(rèn)發(fā)送的時(shí)get請(qǐng)求),使用異步方法(一調(diào)用這個(gè)方法,它會(huì)自動(dòng)開啟一個(gè)子線程去發(fā)送請(qǐng)求,當(dāng)請(qǐng)求成功,數(shù)據(jù)返回的時(shí)候自動(dòng)調(diào)用內(nèi)部的代碼段,這個(gè)代碼段在那個(gè)線程執(zhí)行取決于隊(duì)列,如果是主隊(duì)列,那么在子線程發(fā)送請(qǐng)求成功拿到服務(wù)器的數(shù)據(jù)后,回到主線程中解析數(shù)據(jù),刷新UI界面)。

B.使用代理方法發(fā)送異步請(qǐng)求

要監(jiān)聽服務(wù)器返回的data,所以使用協(xié)議

常見大代理方法如下:

1#pragmamark- NSURLConnectionDataDelegate代理方法

2//當(dāng)接收到服務(wù)器的響應(yīng)(連通了服務(wù)器)時(shí)會(huì)調(diào)用

5-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

7//當(dāng)接收到服務(wù)器的數(shù)據(jù)時(shí)會(huì)調(diào)用(可能會(huì)被調(diào)用多次,每次只傳遞部分?jǐn)?shù)據(jù))

9-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

11//當(dāng)服務(wù)器的數(shù)據(jù)加載完畢時(shí)就會(huì)調(diào)用

13-(void)connectionDidFinishLoading:(NSURLConnection *)connection

15//請(qǐng)求錯(cuò)誤(失?。┑臅r(shí)候調(diào)用(請(qǐng)求超時(shí)\斷網(wǎng)\沒有網(wǎng)\,一般指客戶端錯(cuò)誤)

17-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

使用異步方法發(fā)送get請(qǐng)求的代碼示例:9#import"YYViewController.h"

10#import"MBProgressHUD+MJ.h"

11

12@interfaceYYViewController?()

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@implementationYYViewController

21

22-?(IBAction)login?{

23//1.提前的表單驗(yàn)證

24if(self.username.text.length==0)?{

25[MBProgressHUD?showError:@"請(qǐng)輸入用戶名"];

26return;

27}

28if(self.pwd.text.length==0)?{

29[MBProgressHUD?showError:@"請(qǐng)輸入密碼"];

30return;

31}

32//2.發(fā)送請(qǐng)求給服務(wù)器(帶上賬號(hào)和密碼)

33//添加一個(gè)遮罩,禁止用戶操作

34[MBProgressHUD?showMessage:@"正在努力加載中...."];

35

36//

37//2.1設(shè)置請(qǐng)求路徑

38NSString?*urlStr=[NSString?stringWithFormat:@"http://192.168.1.53:8080/MJServer/login?username=%@&pwd=%@",self.username.text,self.pwd.text];

39NSURL?*url=[NSURL?URLWithString:urlStr];

40

41//2.2創(chuàng)建請(qǐng)求對(duì)象

42//NSURLRequest?*request=[NSURLRequest?requestWithURL:url];//默認(rèn)就是GET請(qǐng)求

43//設(shè)置請(qǐng)求超時(shí)

44NSMutableURLRequest?*request=[NSMutableURLRequest? requestWithURL:url];

45request.timeoutInterval=5.0;

46

47//2.3.發(fā)送請(qǐng)求

48//使用代理發(fā)送異步請(qǐng)求(通常應(yīng)用于文件下載)

49NSURLConnection?*conn=[NSURLConnection?connectionWithRequest:requestdelegate:self];

50[conn?start];

51NSLog(@"已經(jīng)發(fā)出請(qǐng)求---");

52}

53

54#pragmamark-?NSURLConnectionDataDelegate代理方法

55/*

56*當(dāng)接收到服務(wù)器的響應(yīng)(連通了服務(wù)器)時(shí)會(huì)調(diào)用

57*/

58-(void)connection:(NSURLConnection?*)connection?didReceiveResponse:(NSURLResponse?*)response

59{

60NSLog(@"接收到服務(wù)器的響應(yīng)");

61//初始化數(shù)據(jù)

62self.responseData=[NSMutableData?data];

63}

64

65/*

66*當(dāng)接收到服務(wù)器的數(shù)據(jù)時(shí)會(huì)調(diào)用(可能會(huì)被調(diào)用多次,每次只傳遞部分?jǐn)?shù)據(jù))

67*/

68-(void)connection:(NSURLConnection?*)connection?didReceiveData:(NSData?*)data

69{

70NSLog(@"接收到服務(wù)器的數(shù)據(jù)");

71//拼接數(shù)據(jù)

72[self.responseData?appendData:data];

73NSLog(@"%d---%@--",self.responseData.length,[NSThread?currentThread]);

74}

75

76/*

77*當(dāng)服務(wù)器的數(shù)據(jù)加載完畢時(shí)就會(huì)調(diào)用

78*/

79-(void)connectionDidFinishLoading:(NSURLConnection?*)connection

80{

81NSLog(@"服務(wù)器的數(shù)據(jù)加載完畢");

82//隱藏HUD

83[MBProgressHUD?hideHUD];

84

85//處理服務(wù)器返回的所有數(shù)據(jù)

86NSDictionary?*dict=[NSJSONSerialization?JSONObjectWithData:self.responseData?options:NSJSONReadingMutableLeaves?error:nil];

87

88//判斷后,在界面提示登錄信息

89NSString?*error=dict[@"error"];

90if(error)?{

91[MBProgressHUD?showError:error];

92}else

93{

94NSString?*success=dict[@"success"];

95[MBProgressHUD?showSuccess:success];

96}

97NSLog(@"%d---%@--",self.responseData.length,[NSThread?currentThread]);

98}

99/*

100*請(qǐng)求錯(cuò)誤(失敗)的時(shí)候調(diào)用(請(qǐng)求超時(shí)\斷網(wǎng)\沒有網(wǎng)\,一般指客戶端錯(cuò)誤)

101*/

102-(void)connection:(NSURLConnection?*)connection?didFailWithError:(NSError?*)error

103{

104//NSLog(@"請(qǐng)求錯(cuò)誤");

105//隱藏HUD

106[MBProgressHUD?hideHUD];

107[MBProgressHUD?showError:@"網(wǎng)絡(luò)繁忙,請(qǐng)稍后重試!"];

108}

109@end

打補(bǔ)充:

(1)數(shù)據(jù)的處理

在didReceiveData:方法中,拼接接收到的所有數(shù)據(jù),等所有數(shù)據(jù)都拿到后,在connectionDidFinishLoading:方法中進(jìn)行處理

(2)網(wǎng)絡(luò)延遲

在做網(wǎng)絡(luò)開發(fā)的時(shí)候,一定要考慮到網(wǎng)絡(luò)延遲情況的處理,可以在服務(wù)器的代碼設(shè)置一個(gè)斷點(diǎn)模擬。

在服務(wù)器代碼的登錄方法中設(shè)置斷點(diǎn)


設(shè)置請(qǐng)求的最大延遲


模擬器情況:


三、NSMutableURLRequest

NSMutableURLRequest是NSURLRequest的子類,常用方法有

設(shè)置請(qǐng)求超時(shí)等待時(shí)間(超過這個(gè)時(shí)間就算超時(shí),請(qǐng)求失?。? (void)setTimeoutInterval:(NSTimeInterval)seconds;

設(shè)置請(qǐng)求方法(比如GET和POST)- (void)setHTTPMethod:(NSString *)method;

設(shè)置請(qǐng)求體- (void)setHTTPBody:(NSData *)data;

設(shè)置請(qǐng)求頭- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容