前言
iOS的網(wǎng)絡編程祸轮,主要圍繞NSURLConnection和NSURLSession來進行序矩。iOS7之后NSURLSession才出來沃暗,目前看起來NSURLConnection是有被拋棄的跡象冤馏,特別是2016年規(guī)定的所有網(wǎng)絡要支持ipv6典徊,其中竟然沒有說到NSURLConnection内列。
了解一個系統(tǒng)類撵术,需要補充非常多的背景知識,如果沒有這些背景知識话瞧,很難透徹理解整個類是如何運作的嫩与。不過作為api的調用者,往往可以不用管其內部如何實現(xiàn)移稳。Session可以被翻譯為會話蕴纳,兩臺不同的計算機進行通信的過程,其實就是會話的過程个粱。
三步法請求
學習NSURLSession古毛,免不了要和幾個重要的類打交道,比如NSURLSessionConfiguration/NSURLSession/NSURLSessionTask都许。使用起來稻薇,一般都有套路,下面先看看這些套路胶征。
1塞椎、請求的URL
2、用URL生成Request睛低,Http請求里面的請求頭內容
3案狠、生成Session服傍,將Request作為參數(shù),調用Session的dataWithRequest來發(fā)送網(wǎng)絡請求
網(wǎng)絡請求三步法骂铁。對應到代碼:
1吹零、NSURL *url = [NSURL URLWithString:@"www.baidu.com/news/hfu3284"];
2、NSURLRequest *request = [NSURLRequest requestWithURL:url];
3拉庵、NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithRequest:request] resume];
套路只需要照著用就行了灿椅,可以暫時不管為何要按照這些套路來。
了解完基本的使用方式后钞支,就可以根據(jù)使用場景來進行說明了茫蛹。一般app的網(wǎng)絡請求里面,http請求占了很大一部分烁挟,tcp當然也有不過只在IM或者游戲這樣的功能里婴洼。下面看看http請求的幾個場景:
使用場景
網(wǎng)絡編程方面,如果脫離了具體的場景信夫,理解起來特別困難窃蹋,所有場景都是基于Http的,先了解這些使用場景静稻。Http協(xié)議說白了就是兩臺計算機之間要通信警没,通信時的一些規(guī)則。所有的http請求振湾,要么就是由客戶端向服務器請求文件杀迹,要么就是客戶端向服務器上傳文件。
使用場景一:http網(wǎng)絡請求
這個一般是業(yè)務接口押搪,比如拉取json/xml數(shù)據(jù)树酪。目前普遍用afnetworking來做。下面這個例子展示了非常簡單的http網(wǎng)絡請求大州,可以看到請求頭并未拼接參數(shù)续语,稍微復雜一些的網(wǎng)絡參數(shù)則需要根據(jù)是GET還是POST來進行相應處理。
//1厦画、請求字符串
NSString *str = @"http://swiftcafe.io/2015/12/20/nsurlsession/";
//2疮茄、轉化成url
NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
//3、構建request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//4根暑、獲取session
NSURLSession *session = [NSURLSession sharedSession];
//5力试、用session發(fā)送請求,返回一個dataTask
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (data && (error == nil)) {
NSLog(@"data=%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}
else {
NSLog(@"error=%@",error);
} }];
//6排嫌、dataTask創(chuàng)建后是掛起狀態(tài)畸裳,需要調用resume開啟訪問
[dataTask resume];
使用場景二:文件下載
文件下載和一般的http請求不同的是task的不一樣,文件下載使用的是downloadTask淳地,而且返回的block參數(shù)也不同怖糊,需要在block中對location進行移動并保存帅容,否則block執(zhí)行完就會刪除下載的文件。
// 1伍伤、請求字符串
NSString *str = [NSString stringWithFormat:@"http://swiftcafe.io/2015/12/20/nsurlsession/894.png"];
//2凉倚、轉化成url
NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
//3恼布、構建request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//4垦江、獲取session
NSURLSession *session = [NSURLSession sharedSession];
//5原叮、用session發(fā)送請求渔伯,返回一個downloadTask
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil) {
//下載成功
} else {
//下載失敗
}
}];
//6苫费、downloadTask創(chuàng)建后是掛起狀態(tài)被环,需要調用resume開啟訪問
[downloadTask resume];
使用場景三:文件上傳
文件上傳則需要用到POST方法楼雹,套路其實都很接近荐开,只不過會有一個formData參數(shù)需要傳入付翁,這個參數(shù)就是一些上傳文件的NSData。
// 1晃听、請求字符串
NSString *str = [NSString stringWithFormat:@"http://swiftcafe.io/2015/12/20/nsurlsession/thumbnail.php"];
//2百侧、轉化成url
NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]];
//3、構建request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
//4能扒、獲取session
NSURLSession *session = [NSURLSession sharedSession];
//5佣渴、用session發(fā)送請求,返回一個uploadTask
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:[NSData dataWithContentsOfFile:@"IMG_0359.jpg"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error == nil) {
NSLog(@"upload success:%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
} else {
NSLog(@"upload error:%@",error);
}
}];
//6初斑、開始上傳
[uploadTask resume];
表單數(shù)據(jù)上傳
表單數(shù)據(jù)的上傳會比較麻煩辛润,需要設置請求體的內容。格式如下:
請求頭:
Content-Type:multipart/form-data;boundary=------------1345123513452323412352
請求體:
------------1345123513452323412352--
Content-Disposition:form-data; name="表單控件名"; filename="文件名"
Content-Type:MIME type
數(shù)據(jù)
--------------1345123513452323412352--
NSData *imagedata = UIImageJPEGRepresentation(image, 0.7);
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://localhost/dashboard/test.php"]];
[request setHTTPMethod:@"POST"];
[request setTimeoutInterval:20];
NSMutableData *body = [NSMutableData data];
//設置表單項分隔符
NSString *boundary = @"---------------------------14737809831466499882746641449";
//設置內容類型
NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary];
[request addValue:contentType forHTTPHeaderField: @"Content-Type"];
//寫入圖片的內容
[body appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"PIC_DATA1.jpg\"\r\n",@"file"] dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:[@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[body appendData:imagedata];
[body appendData:[[NSString stringWithFormat:@"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
//寫入尾部內容
[body appendData:[[NSString stringWithFormat:@"--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
[request setHTTPBody:body];
NSURLSessionUploadTask * uploadtask = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSString * htmlString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@", htmlString);
}];
[uploadtask resume];