iOS的網(wǎng)絡(luò)編程主要涉及兩者:客戶端和服務(wù)器端参萄,上傳和下載數(shù)據(jù)都是客戶端通過訪問服務(wù)器端來實現(xiàn)的。
服務(wù)器端開發(fā)語言有Java酣倾,.Net舵揭,C/C++,PHP躁锡,Ruby午绳,Python等,而手機(jī)客戶端的開發(fā)語言有OC映之,Java等與后端開發(fā)語言不同拦焚,因此要實現(xiàn)服務(wù)器端與客戶端的數(shù)據(jù)傳輸必然要有約定一種數(shù)據(jù)傳輸?shù)母袷胶蛡鬏攨f(xié)議,否則二者不能進(jìn)行交流杠输。這個格式可以為JSON赎败,XML等,傳輸協(xié)議我們熟知的有http(超文本傳輸協(xié)議)抬伺,它是一個通信規(guī)則螟够,注意:這個協(xié)議永遠(yuǎn)都是客戶端發(fā)起請求,服務(wù)器端回送響應(yīng)峡钓。
HTTP請求包:客戶端發(fā)送一個HTTP請求,是向服務(wù)器提交了一個HTTP請求包若河。
請求包的結(jié)構(gòu):請求頭和請求體能岩。
請求體的數(shù)據(jù)格式:JSON、XML萧福、符號拼接拉鹃,客戶端向服務(wù)器提交的數(shù)據(jù)都放在請求體中或者后面的URL中。
HTTP請求包包括GET請求和POST請求:
GET請求是客戶端向服務(wù)器索取數(shù)據(jù)的一種請求方式,(只包含請求頭)膏燕。
POST請求是客戶端向服務(wù)器提交數(shù)據(jù)的方式钥屈,(包含請求頭和請求體)。
HTTP響應(yīng)包:服務(wù)器收到請求之后向客戶端回應(yīng)了一個HTTP響應(yīng)包坝辫。
響應(yīng)包結(jié)構(gòu):響應(yīng)頭和響應(yīng)體篷就。
服務(wù)器通過響應(yīng)體將數(shù)據(jù)傳給客戶端,數(shù)據(jù)格式有JSON近忙、XML竭业。
同步請求:數(shù)據(jù)的請求過程在主線程執(zhí)行的,網(wǎng)絡(luò)數(shù)據(jù)傳輸?shù)倪^程會導(dǎo)致主線程堵塞及舍。
異步請求:數(shù)據(jù)的請求過程在多線程執(zhí)行的未辆,保持主線程的流暢性,UI界面的渲染與刷新在主線程中锯玛,主線程不流暢會導(dǎo)致UI界面卡頓咐柜。
下面來點干貨
網(wǎng)絡(luò)組件:NSURLSession可以實現(xiàn)上傳,下載攘残,處理認(rèn)證等工具拙友,能處理http協(xié)議中的所用事情。
NSURLSession由NSURLSessionConfiguration和可選代理(optional delegate)構(gòu)成肯腕。再根據(jù)你的網(wǎng)絡(luò)需求通過NSURLSessionTask來創(chuàng)建session献宫。
GET請求:
#import "ViewController.h"
@interface?ViewController?()
@property?(weak,?nonatomic)?IBOutlet?UITextView?*textView;
@end
@implementation?ViewController
-?(void)viewDidLoad?{
[super?viewDidLoad];
}
-?(IBAction)GET:(id)sender?{
/*
使用NSURLSession?進(jìn)行網(wǎng)絡(luò)請求的幾個步驟
1.構(gòu)造NSURL地址
2.構(gòu)造請求對象?NSURLRequest
3.構(gòu)造NSURLSessionConfiguration配置文件,可選
4.構(gòu)造NSURLSession網(wǎng)絡(luò)會話對象
5.創(chuàng)建網(wǎng)絡(luò)任務(wù)
6.執(zhí)行網(wǎng)絡(luò)任務(wù)实撒,發(fā)送網(wǎng)絡(luò)請求
*/
//1
NSURL?*url=?[NSURL?URLWithString:@"http://piao.163.com/m/cinema/list.html?app_id=1&mobileType=iPhone&ver=2.6&channel=appstore&deviceId=9E89CB6D-A62F-438C-8010-19278D46A8A6&apiVer=6&city=110000"];
//2?使用URL?創(chuàng)建一個可變的請求對象
NSMutableURLRequest?*request=?[NSMutableURLRequest?requestWithURL:url];
//設(shè)置請求對象
//請求方式
request.HTTPMethod=?@"GET";
//超時時間
request.timeoutInterval=60;
//設(shè)置請求頭中的參數(shù)
//?[request?setValue:@"1533"?forHTTPHeaderField:@"cinema_id"];
//3?創(chuàng)建會話對象??默認(rèn)的會話
NSURLSession?*session=?[NSURLSession?sharedSession];
//4?創(chuàng)建網(wǎng)絡(luò)任務(wù)
//NSURLSessionTask?抽象類??使用其子類?dataTask,uploadTask,downloadTask
NSURLSessionDataTask?*dataTask=?[session?dataTaskWithRequest:request?completionHandler:^(NSData?*?_Nullable?data,?NSURLResponse?*?_Nullable?response,?NSError?*?_Nullable?error)?{
//判斷錯誤
if?(error)?{
NSLog(@"請求出錯:%@",?error);
return;
}
NSError?*jsonError=nil;
//Json解析
NSDictionary?*dic=?[NSJSONSerialization?JSONObjectWithData:data?options:NSJSONReadingMutableContainers?error:&jsonError];
NSString?*jsonText=?[NSString?stringWithFormat:@"%@",?dic];
//回到主線程?來刷新文字
[_textView?performSelectorOnMainThread:@selector(setText:)?withObject:jsonText?waitUntilDone:NO];
}];
//5?開啟任務(wù)
[dataTask?resume];
}
POST請求:
#import "ViewController.h"
@interface?ViewController?()
@property?(weak,?nonatomic)?IBOutlet?UITextView?*textView;
@end
@implementation?ViewController
-?(void)viewDidLoad?{
[super?viewDidLoad];
}
-?(IBAction)POST:(id)sender?{
/*
使用NSURLSession?進(jìn)行網(wǎng)絡(luò)請求的幾個步驟
1.構(gòu)造NSURL地址
2.構(gòu)造請求對象?NSURLRequest
3.構(gòu)造NSURLSessionConfiguration配置文件姊途,可選
4.構(gòu)造NSURLSession網(wǎng)絡(luò)會話對象
5.創(chuàng)建網(wǎng)絡(luò)任務(wù)
6.執(zhí)行網(wǎng)絡(luò)任務(wù),發(fā)送網(wǎng)絡(luò)請求
*/
NSURL?*url=?[NSURL?URLWithString:@"http://piao.163.com/m/cinema/schedule.html?app_id=1&mobileType=iPhone&ver=2.6&channel=appstore&deviceId=9E89CB6D-A62F-438C-8010-19278D46A8A6&apiVer=6&city=110000"];
NSMutableURLRequest?*request=?[NSMutableURLRequest?requestWithURL:url];
//設(shè)置POST請求
request.HTTPMethod=?@"POST";
request.timeoutInterval=60;
//設(shè)置請求體
//cinema_id=1533
NSData?*bodyData=?[@"cinema_id=1533"?dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody=bodyData;
NSURLSession?*session=?[NSURLSession?sharedSession];
NSURLSessionDataTask?*dataTask=?[session?dataTaskWithRequest:request?completionHandler:^(NSData?*?_Nullable?data,?NSURLResponse?*?_Nullable?response,?NSError?*?_Nullable?error)?{
NSDictionary?*dic=?[NSJSONSerialization?JSONObjectWithData:data?options:NSJSONReadingMutableContainers?error:nil];
NSString?*jsonString=?[NSString?stringWithFormat:@"%@",?dic];
[_textView?performSelectorOnMainThread:@selector(setText:)?withObject:jsonString?waitUntilDone:NO];
//獲取響應(yīng)包
//將response?轉(zhuǎn)化為一個子類的HTTPURLResponse
NSHTTPURLResponse?*httpResponse=?(NSHTTPURLResponse?*)response;
//打印狀態(tài)碼
NSLog(@"狀態(tài)碼:%li",?httpResponse.statusCode);
//獲取響應(yīng)頭
NSDictionary?*responseHeader=httpResponse.allHeaderFields;
NSLog(@"響應(yīng)頭:%@",?responseHeader);
}];
//開始網(wǎng)絡(luò)任務(wù)
[dataTask?resume];
}
NSURLSessionConfiguration配置網(wǎng)絡(luò)會話
@implementation?ViewController
-?(void)viewDidLoad?{
[super?viewDidLoad];
//使用NSURLSessionConfiguration?來配置網(wǎng)絡(luò)會話
/*
1?構(gòu)造URL地址
2?創(chuàng)建Request對象(可選)
3?構(gòu)建?NSURLSessionConfiguration?對象
4?通過配置?來構(gòu)建網(wǎng)絡(luò)會話
5?創(chuàng)建網(wǎng)絡(luò)任務(wù)
6?開啟任務(wù)
*/
_data=?[NSMutableData?data];
//URL
NSURL?*url=?[NSURL?URLWithString:@"http://piao.163.com/m/cinema/list.html?app_id=1&mobileType=iPhone&ver=2.6&channel=appstore&deviceId=9E89CB6D-A62F-438C-8010-19278D46A8A6&apiVer=6&city=110000"];
//NSURLSessionConfiguration
/*
defaultSessionConfiguration;???默認(rèn)的網(wǎng)絡(luò)會話類型知态,會進(jìn)行自動的緩存
ephemeralSessionConfiguration;?臨時會話捷兰,不會進(jìn)行任何緩存
backgroundSessionConfigurationWithIdentifier:(NSString?*)identifier?后臺會話,可以在程序進(jìn)入到后臺之后负敏,繼續(xù)網(wǎng)絡(luò)任務(wù)
*/
NSURLSessionConfiguration?*config=?[NSURLSessionConfiguration?defaultSessionConfiguration];
//config的常用設(shè)置
//config.requestCachePolicy?設(shè)置緩存策略
//config.networkServiceType?網(wǎng)絡(luò)服務(wù)類型
config.timeoutIntervalForRequest=20;?//網(wǎng)絡(luò)超時時間
//config.HTTPAdditionalHeaders?請求頭的設(shè)置
//config.discretionary?節(jié)能設(shè)置
config.allowsCellularAccess=YES;?//是否使用蜂窩網(wǎng)絡(luò)數(shù)據(jù)
//創(chuàng)建會話對象
//delegateQueue:用于指定代理方法所運行的隊列
NSURLSession?*session=?[NSURLSession?sessionWithConfiguration:config?delegate:self?delegateQueue:[NSOperationQueue?mainQueue]];
//創(chuàng)建網(wǎng)絡(luò)任務(wù)
NSURLSessionDataTask?*task=?[session?dataTaskWithURL:url];
[task?resume];
}
#pragma?mark?-?NSURLSessionDataDelegate
//當(dāng)一次網(wǎng)絡(luò)請求開始贡茅,收到返回的響應(yīng)頭之后所調(diào)用的方法
-?(void)URLSession:(NSURLSession?*)session
dataTask:(NSURLSessionDataTask?*)dataTask
didReceiveResponse:(NSURLResponse?*)response
completionHandler:(void?(^)(NSURLSessionResponseDisposition?disposition))completionHandler?{
NSLog(@"response:?%@",response);
//將NSURLResponse的對象,強(qiáng)轉(zhuǎn)成子類NSHTTPURLResponse對象
NSHTTPURLResponse?*httpResponse=?(NSHTTPURLResponse?*)response;
NSLog(@"狀態(tài)碼:%li",?httpResponse.statusCode);
//completionHandler?完成后的回調(diào)
//通過執(zhí)行此bolck?來設(shè)定接下來網(wǎng)絡(luò)訪問
/*
NSURLSessionResponseCancel=0,???????取消網(wǎng)絡(luò)訪問其做,不在讀取響應(yīng)體
NSURLSessionResponseAllow=1,????????允許本次網(wǎng)絡(luò)訪問顶考,繼續(xù)接受數(shù)據(jù)
NSURLSessionResponseBecomeDownload=2,?轉(zhuǎn)化為downLoadTask
NSURLSessionResponseBecomeStream
*/
completionHandler(NSURLSessionResponseAllow);
}
//響應(yīng)體的接受
-?(void)URLSession:(NSURLSession?*)session?dataTask:(NSURLSessionDataTask?*)dataTask?didReceiveData:(NSData?*)data?{
//接收到響應(yīng)體中的數(shù)據(jù)時??調(diào)用的方法
NSLog(@"data.lenght=?%li",?data.length);
//將每次接收到的數(shù)據(jù),拼接到全局變量中
[_data?appendData:data];
}
//響應(yīng)完成
-?(void)URLSession:(NSURLSession?*)session?task:(NSURLSessionTask?*)task?didCompleteWithError:(NSError?*)error?{
if?(error)?{
NSLog(@"%@",?error);
_data=nil;
}?else?{
//讀取無誤妖泄,Json解析
NSDictionary?*dic=?[NSJSONSerialization?JSONObjectWithData:_data?options:NSJSONReadingMutableContainers?error:nil];
NSLog(@"dic=?%@",?dic);
}
}