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ù)器,并收集來(lái)自服務(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)求代碼示例:

1//2//YYViewController.m3//01-NSURLConnection的使用(GET)4//5//Created by apple on 14-6-28.6//Copyright (c) 2014年 itcase. All rights reserved.7//89#import"YYViewController.h"10#import"MBProgressHUD+MJ.h"1112@interfaceYYViewController ()13@property (weak, nonatomic) IBOutlet UITextField *username;14@property (weak, nonatomic) IBOutlet UITextField *pwd;15-(IBAction)login;1617@end1819@implementationYYViewController2021-(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)代碼示例:

1//2//YYViewController.m3//01-NSURLConnection的使用(GET)4//5//Created by apple on 14-6-28.6//Copyright (c) 2014年 itcase. All rights reserved.7//89#import"YYViewController.h"10#import"MBProgressHUD+MJ.h"1112@interfaceYYViewController ()13@property (weak, nonatomic) IBOutlet UITextField *username;14@property (weak, nonatomic) IBOutlet UITextField *pwd;15-(IBAction)login;1617@end1819@implementationYYViewController2021-(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:@"正在努力加載中...."];3435//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];3940//2.創(chuàng)建請(qǐng)求對(duì)象41NSURLRequest *request=[NSURLRequest requestWithURL:url];4243//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í)行操作)4748//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];5758//解析data59/*60{"success":"登錄成功"}61{"error":"用戶名不存在"}62{"error":"密碼不正確"}63*/64NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];65NSLog(@"%@",dict);6667//判斷后,在界面提示登錄信息68NSString *error=dict[@"error"];69if(error) {70[MBProgressHUD showError:error];71}else72{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)求失?。?NSLog(@"--block回調(diào)數(shù)據(jù)--%@---%d", [NSThread currentThread],data.length);5//隱藏HUD,刷新UI的操作一定要放在主線程執(zhí)行6[MBProgressHUD hideHUD];78//解析data9/*10{"success":"登錄成功"}11{"error":"用戶名不存在"}12{"error":"密碼不正確"}13*/14if(data) {//請(qǐng)求成功15NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];16NSLog(@"%@",dict);1718//判斷后,在界面提示登錄信息19NSString *error=dict[@"error"];20if(error) {21[MBProgressHUD showError:error];22}else23{24NSString *success=dict[@"success"];25[MBProgressHUD showSuccess:success];26}27}else//請(qǐng)求失敗28{29[MBProgressHUD showError:@"網(wǎng)絡(luò)繁忙,請(qǐng)稍后重試!"];30}3132}];

解析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代理方法23//當(dāng)接收到服務(wù)器的響應(yīng)(連通了服務(wù)器)時(shí)會(huì)調(diào)用45-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response67//當(dāng)接收到服務(wù)器的數(shù)據(jù)時(shí)會(huì)調(diào)用(可能會(huì)被調(diào)用多次,每次只傳遞部分?jǐn)?shù)據(jù))89-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data1011//當(dāng)服務(wù)器的數(shù)據(jù)加載完畢時(shí)就會(huì)調(diào)用1213-(void)connectionDidFinishLoading:(NSURLConnection *)connection1415//請(qǐng)求錯(cuò)誤(失?。┑臅r(shí)候調(diào)用(請(qǐng)求超時(shí)\斷網(wǎng)\沒有網(wǎng)\,一般指客戶端錯(cuò)誤)1617-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

使用異步方法發(fā)送get請(qǐng)求的代碼示例:

1//2//YYViewController.m3//01-NSURLConnection的使用(GET)4//5//Created by apple on 14-6-28.6//Copyright (c) 2014年 itcase. All rights reserved.7//89#import"YYViewController.h"10#import"MBProgressHUD+MJ.h"1112@interfaceYYViewController ()13@property (weak, nonatomic) IBOutlet UITextField *username;14@property (weak, nonatomic) IBOutlet UITextField *pwd;15@property(nonatomic,strong)NSMutableData *responseData;16-(IBAction)login;1718@end1920@implementationYYViewController2122-(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:@"正在努力加載中...."];3536//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];4041//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;4647//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}5354#pragmamark- NSURLConnectionDataDelegate代理方法55/*56*當(dāng)接收到服務(wù)器的響應(yīng)(連通了服務(wù)器)時(shí)會(huì)調(diào)用57*/58-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response59{60NSLog(@"接收到服務(wù)器的響應(yīng)");61//初始化數(shù)據(jù)62self.responseData=[NSMutableData data];63}6465/*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 *)data69{70NSLog(@"接收到服務(wù)器的數(shù)據(jù)");71//拼接數(shù)據(jù)72[self.responseData appendData:data];73NSLog(@"%d---%@--",self.responseData.length,[NSThread currentThread]);74}7576/*77*當(dāng)服務(wù)器的數(shù)據(jù)加載完畢時(shí)就會(huì)調(diào)用78*/79-(void)connectionDidFinishLoading:(NSURLConnection *)connection80{81NSLog(@"服務(wù)器的數(shù)據(jù)加載完畢");82//隱藏HUD83[MBProgressHUD hideHUD];8485//處理服務(wù)器返回的所有數(shù)據(jù)86NSDictionary *dict=[NSJSONSerialization JSONObjectWithData:self.responseData options:NSJSONReadingMutableLeaves error:nil];8788//判斷后,在界面提示登錄信息89NSString *error=dict[@"error"];90if(error) {91[MBProgressHUD showError:error];92}else93{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 *)error103{104//NSLog(@"請(qǐng)求錯(cuò)誤");105//隱藏HUD106[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;