一.為什么要使用NSURLSession來替換NSURLConnection
1.在iOS9.0之后署隘,以前使用的NSURLConnection過期扬蕊,蘋果推薦使用NSURLSession來替換NSURLConnection完成網(wǎng)路請求相關(guān)操作歪架。
2.NSURLSession的優(yōu)勢:
- NSURLSession支持http2.0協(xié)議
- 處理下載任務的時候可以直接把數(shù)據(jù)下載到磁盤中
- 支持后臺下載和上傳
- 同一個session發(fā)送多次請求芥永,只需要建立一次連接(復用了TCP)
- 提供了全局的session并且可以統(tǒng)一配置咧纠,使用更加方便
- 下載的時候是多線程異步處理,效率更高
3.NSURLSession的使用非常簡單丛肢,先根據(jù)會話對象創(chuàng)建一個請求Task,然后執(zhí)行該Task即可
4.NSURLSessionTask及其子類
NSURLSessionTask
本身是一個抽象類剿干,在使用的時候蜂怎,通常是根據(jù)具體的需求使用它的幾個子類
NSURLSessionDataTask
可以用來發(fā)送常見的Get,Post請求置尔,既可以用來上傳也可以用來下載
NSURLSessionDownloadTask
可以用來發(fā)送下載請求杠步,專門用來下載數(shù)據(jù)
NSURLSessionUploadTask
可以用來發(fā)送上傳請求,專門用來上傳數(shù)據(jù)
二.使用URLSession發(fā)送Get請求
2.1.過程:
1.確定請求路徑(一般由公司的后臺開發(fā)人員以接口文檔的方式提供)榜轿,Get請求參數(shù)直接跟在URL后面
2.創(chuàng)建請求對象(默認包含了請求頭和請求方法【Get】)幽歼,此步驟可以省略
3.創(chuàng)建會話對象(NSURLSession)
4.根據(jù)會話對象創(chuàng)建請求任務(NSURLSessionDataTask)
5.執(zhí)行Task
6.當?shù)玫椒掌鞣祷氐捻憫螅馕鰯?shù)據(jù)(XML|JSON|HTTP)
2.2.代碼示例:
1.確定請求路徑
NSURL *url = [NSURL URLWithString:
@"http://127.0.0.1/AF_Hello_Get.php?name=jack&password=123"];
對請求路徑的說明:
http://127.0.0.1/AF_Hello_Get.php?name=jack&password=123
協(xié)議頭(http://)+主機地址(127.0.0.1)+接口名稱(AF_Hello_Get.php)+?+參數(shù)1(name=jack)+&+參數(shù)2(password=123)
Get請求差导,直接把請求參數(shù)跟在URL的后面以?隔開试躏,多個參數(shù)之間以&符號拼接
2.創(chuàng)建請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
請求對象內(nèi)部默認已經(jīng)包含了請求頭和請求方法(GET)
3.獲得會話對象
NSURLSession *session = [NSURLSession sharedSession];
4.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求),Get請求有兩種方式
NSURLSessionDataTask *firsttask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
第一個參數(shù):請求路徑
第二個參數(shù):completionHandler回調(diào)(請求完成【成功|失敗】的回調(diào))
data:響應體信息(期望的數(shù)據(jù))
response:響應頭信息,主要是對服務器端的描述
error:錯誤信息设褐,如果請求失敗颠蕴,則error有值注意:
1)該方法內(nèi)部會自動將請求路徑包裝成一個請求對象泣刹,該請求對象默認包含了請求頭信息和請求方法(GET)
2)如果要發(fā)送的是POST請求,則不能使用該方法
NSURLSessionDataTask *secondtask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
第一個參數(shù):請求對象
第二個參數(shù):completionHandler回調(diào)(請求完成【成功|失敗】的回調(diào))
data:響應體信息(期望的數(shù)據(jù))
response:響應頭信息犀被,主要是對服務器端的描述
error:錯誤信息椅您,如果請求失敗,則error有值
5.解析服務器返回的數(shù)據(jù)
//說明(此處返回的數(shù)據(jù)是JSON格式的寡键,因此使用NSJSONSerialization進行反序列化處理)
NSLog(@"Get請求返回的響應信息:%@",[NSJSONSerialization
JSONObjectWithData:data options:kNilOptions error:nil]);
6.執(zhí)行任務
[firsttask resume];
[secondtask resume];
三.使用URLSession發(fā)送Post請求
2.1.過程:
1.確定請求路徑(一般由公司的后臺開發(fā)人員以接口文檔的方式提供)
2.創(chuàng)建可變的請求對象(因為需要修改)掀泳,此步驟不可以省略
3.修改請求方法為POST
4.設(shè)置請求體,把參數(shù)轉(zhuǎn)換為二進制數(shù)據(jù)并設(shè)置請求體
5.創(chuàng)建會話對象(NSURLSession)
6.根據(jù)會話對象創(chuàng)建請求任務(NSURLSessionDataTask)
7.執(zhí)行Task
8.當?shù)玫椒掌鞣祷氐捻憫笪餍馕鰯?shù)據(jù)(XML|JSON|HTTP)
2.2代碼示例
1.確定請求路徑
NSURL *url_post = [NSURL URLWithString:
@"http://127.0.0.1/AF_Hello_Post.php"];
對請求路徑的說明:
http://127.0.0.1/AF_Hello_Post.php
協(xié)議頭(http://)+主機地址(127.0.0.1)+接口名稱(AF_Hello_Get.php))
POST請求需要修改請求方法為POST员舵,并把參數(shù)轉(zhuǎn)換為二進制數(shù)據(jù)設(shè)置為請求體
2.創(chuàng)建可變的請求對象
NSMutableURLRequest *request_post = [NSMutableURLRequest
requestWithURL:url_post];
3.修改請求方法為POST
request_post.HTTPMethod = @"POST";
4.設(shè)置請求體
request_post.HTTPBody = [@"name=jack&password=123"
dataUsingEncoding:NSUTF8StringEncoding];
5.創(chuàng)建會話對象
NSURLSession *session_post = [NSURLSession sharedSession];
6.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求)
NSURLSessionDataTask *task_post = [session_post dataTaskWithRequest:request_post completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
第一個參數(shù):請求對象
第二個參數(shù):completionHandler回調(diào)(請求完成【成功|失敗】的回調(diào))
data:響應體信息(期望的數(shù)據(jù))
response:響應頭信息,主要是對服務器端的描述
error:錯誤信息藕畔,如果請求失敗马僻,則error有值
7.解析服務器返回的數(shù)據(jù)
//說明:(此處返回的數(shù)據(jù)是JSON格式的,因此使用NSJSONSerialization進行反序列化處理)
NSLog(@"Post請求返回的響應信息:%@",[NSJSONSerialization JSONObjectWithData:_mData options:kNilOptions error:nil]);
8.執(zhí)行任務
[task_post resume];
四.使用代理方法請求
有的時候注服,我們可能需要監(jiān)聽網(wǎng)絡請求的過程韭邓,那么就需要用到代理方法。
1.確定請求路徑
NSURL *url = [NSURL URLWithString:
@"http://127.0.0.1/AF_Hello_Get.php?name=jack&password=123"];
2.創(chuàng)建請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
3.獲得會話對象,并設(shè)置代理
NSURLSessionConfiguration *config = [NSURLSessionConfiguration
defaultSessionConfiguration];
NSURLSession *session = [NSURLSession
sessionWithConfiguration:config
delegate:self
delegateQueue:[NSOperationQueue mainQueue]];
第一個參數(shù):會話對象的配置信息defaultSessionConfiguration 表示默認配置
第二個參數(shù):誰成為代理溶弟,此處為控制器本身即self
第三個參數(shù):隊列女淑,該隊列決定代理方法在哪個線程中調(diào)用,可以傳主隊列|非主隊列
[NSOperationQueue mainQueue] 主隊列: 代理方法在主線程中調(diào)用
[[NSOperationQueue alloc]init] 非主隊列: 代理方法在子線程中調(diào)用
4.遵從協(xié)議辜御,并定義一個變量用于接受信息
@interface ViewController ()<NSURLSessionDataDelegate>
/**存放接受的信息*/
@property (nonatomic,strong) NSMutableData *mData;
@end
5.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求)
NSURLSessionDataTask *task = [session
dataTaskWithRequest:request];
6.執(zhí)行任務
[task resume];
7.代理方法鸭你,和NSURLConnection的類似
//1.接收到服務器響應的時候調(diào)用該方法
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
//如果需要知道這個HTTP的所有信息,就需要獲得NSURLResponse的子類
NSHTTPURLResponse *htttpResponse = (NSHTTPURLResponse *)response;
//打印信息
NSLog(@"響應頭信息:%@",htttpResponse.allHeaderFields);
//定義一個容器用于接受服務器返回的數(shù)據(jù)
self.mData = [NSMutableData data];
//注意:和NSURLConnection不同點在于接收到響應信息之后,需要使用completionHandler回調(diào)告訴系統(tǒng)應該如何處理服務器返回的數(shù)據(jù)
//默認是取消的(NSURLSessionResponseCancel),繼續(xù)傳遞數(shù)據(jù)(NSURLSessionResponseAllow)
completionHandler(NSURLSessionResponseAllow);
}
//2.接收到服務器返回數(shù)據(jù)的時候會調(diào)用該方法我抠,如果數(shù)據(jù)較大那么該方法可能會調(diào)用多次
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
//拼接服務器返回的數(shù)據(jù)
[_mData appendData:data];
}
//3.當請求完成(成功|失敗)的時候會調(diào)用該方法苇本,如果請求失敗,則error有值
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
//解析服務器返回的數(shù)據(jù)
//說明:(此處返回的數(shù)據(jù)是JSON格式的菜拓,因此使用NSJSONSerialization進行反序列化處理)
NSLog(@"代理方法返回的響應信息:%@",[NSJSONSerialization JSONObjectWithData:_mData options:kNilOptions error:nil]);
}
五.完整代碼以及運行結(jié)果
本地服務器的php代碼
//AF_Hello_Get.php
<?PHP
#獲取用戶輸入的姓名和密碼
$name = $_GET["name"];
$pwd = $_GET["password"];
$user = array(
"name"=>$name,
"password"=>$pwd,
);
$result = array(
"user"=>$user,
"total"=>"2",
"status"=>0,
);
header('Content-Type:application/json');
echo json_encode($result);
?>
//AF_Hello_Post.php
<?PHP
#獲取用戶輸入的姓名和密碼
$name = $_POST["name"];
$pwd = $_POST["password"];
$user = array(
"name"=>$name,
"password"=>$pwd,
);
$result = array(
"user"=>$user,
"total"=>"2",
"status"=>0,
);
header('Content-Type:application/json');
echo json_encode($result);
?>
iOS的info.plist文件配置
iOS代碼
//
// ViewController.m
// NSURLSession
//
// Created by 許磊 on 2019/5/17.
// Copyright ? 2019年 許磊. All rights reserved.
//
#import "ViewController.h"
@interface ViewController ()<NSURLSessionDataDelegate>
/**存放接受的信息*/
@property (nonatomic,strong) NSMutableData *mData;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
#pragma mark -------Get請求 ---------
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/AF_Hello_Get.php?name=jack&password=123"];
//2.創(chuàng)建請求對象
//請求對象內(nèi)部默認已經(jīng)包含了請求頭和請求方法(GET)
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.獲得會話對象
NSURLSession *session = [NSURLSession sharedSession];
//4.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求)
/*
第一個參數(shù):請求路徑
第二個參數(shù):completionHandler回調(diào)(請求完成【成功|失敗】的回調(diào))
data:響應體信息(期望的數(shù)據(jù))
response:響應頭信息瓣窄,主要是對服務器端的描述
error:錯誤信息,如果請求失敗纳鼎,則error有值
注意:
1)該方法內(nèi)部會自動將請求路徑包裝成一個請求對象俺夕,該請求對象默認包含了請求頭信息和請求方法(GET)
2)如果要發(fā)送的是POST請求,則不能使用該方法
*/
NSURLSessionDataTask *firsttask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//5.解析服務器返回的數(shù)據(jù)
//說明:(此處返回的數(shù)據(jù)是JSON格式的贱鄙,因此使用NSJSONSerialization進行反序列化處理)
NSLog(@"Get請求返回的響應信息1:%@",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
//4.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求)
/*
第一個參數(shù):請求對象
第二個參數(shù):completionHandler回調(diào)(請求完成【成功|失敗】的回調(diào))
data:響應體信息(期望的數(shù)據(jù))
response:響應頭信息劝贸,主要是對服務器端的描述
error:錯誤信息,如果請求失敗逗宁,則error有值
*/
NSURLSessionDataTask *secondtask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//5.解析服務器返回的數(shù)據(jù)
//說明:(此處返回的數(shù)據(jù)是JSON格式的映九,因此使用NSJSONSerialization進行反序列化處理)
NSLog(@"Get請求返回的響應信息2:%@",[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
//開始下載
[firsttask resume];
[secondtask resume];
#pragma mark -------Post請求 ---------
//1.確定請求路徑
NSURL *url_post = [NSURL URLWithString:@"http://127.0.0.1/AF_Hello_Post.php"];
//2.創(chuàng)建可變的請求對象
NSMutableURLRequest *request_post = [NSMutableURLRequest requestWithURL:url_post];
//3.修改請求方法為POST
request_post.HTTPMethod = @"POST";
//4.設(shè)置請求體
request_post.HTTPBody = [@"name=jack&password=123" dataUsingEncoding:NSUTF8StringEncoding];
//5.創(chuàng)建會話對象
NSURLSession *session_post = [NSURLSession sharedSession];
//6.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求)
/*
第一個參數(shù):請求對象
第二個參數(shù):completionHandler回調(diào)(請求完成【成功|失敗】的回調(diào))
data:響應體信息(期望的數(shù)據(jù))
response:響應頭信息,主要是對服務器端的描述
error:錯誤信息瞎颗,如果請求失敗件甥,則error有值
*/
NSURLSessionDataTask *task_post = [session_post dataTaskWithRequest:request_post completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//7.解析服務器返回的數(shù)據(jù)
//說明:(此處返回的數(shù)據(jù)是JSON格式的捌议,因此使用NSJSONSerialization進行反序列化處理)
NSLog(@"Post請求返回的響應信息:%@",[NSJSONSerialization JSONObjectWithData:_mData options:kNilOptions error:nil]);
}];
//8.執(zhí)行任務
[task_post resume];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
//1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://127.0.0.1/AF_Hello_Get.php?name=jack&password=123"];
//2.創(chuàng)建請求對象
//請求對象內(nèi)部默認已經(jīng)包含了請求頭和請求方法(GET)
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.獲得會話對象,并設(shè)置代理
/*
第一個參數(shù):會話對象的配置信息defaultSessionConfiguration 表示默認配置
第二個參數(shù):誰成為代理,此處為控制器本身即self
第三個參數(shù):隊列引有,該隊列決定代理方法在哪個線程中調(diào)用瓣颅,可以傳主隊列|非主隊列
[NSOperationQueue mainQueue] 主隊列: 代理方法在主線程中調(diào)用
[[NSOperationQueue alloc]init] 非主隊列: 代理方法在子線程中調(diào)用
*/
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//4.根據(jù)會話對象創(chuàng)建一個Task(發(fā)送請求)
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
//5.執(zhí)行任務
[task resume];
}
//1.接收到服務器響應的時候調(diào)用該方法
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
//如果需要知道這個HTTP的所有信息,就需要獲得NSURLResponse的子類
NSHTTPURLResponse *htttpResponse = (NSHTTPURLResponse *)response;
//打印信息
NSLog(@"響應頭信息:%@",htttpResponse.allHeaderFields);
//定義一個容器用于接受服務器返回的數(shù)據(jù)
self.mData = [NSMutableData data];
//注意:和NSURLConnection不同點在于接收到響應信息之后,需要使用completionHandler回調(diào)告訴系統(tǒng)應該如何處理服務器返回的數(shù)據(jù)
//默認是取消的(NSURLSessionResponseCancel),繼續(xù)傳遞數(shù)據(jù)(NSURLSessionResponseAllow)
completionHandler(NSURLSessionResponseAllow);
}
//2.接收到服務器返回數(shù)據(jù)的時候會調(diào)用該方法譬正,如果數(shù)據(jù)較大那么該方法可能會調(diào)用多次
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
//拼接服務器返回的數(shù)據(jù)
[_mData appendData:data];
}
//3.當請求完成(成功|失敗)的時候會調(diào)用該方法宫补,如果請求失敗,則error有值
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
//解析服務器返回的數(shù)據(jù)
//說明:(此處返回的數(shù)據(jù)是JSON格式的曾我,因此使用NSJSONSerialization進行反序列化處理)
NSLog(@"代理方法返回的響應信息:%@",[NSJSONSerialization JSONObjectWithData:_mData options:kNilOptions error:nil]);
}
@end
運行結(jié)果
2019-05-20 19:24:19.606069+0800 NSURLSession[7076:151492] 響應頭信息:{
Connection = "Keep-Alive";
"Content-Length" = 64;
"Content-Type" = "application/json";
Date = "Mon, 20 May 2019 11:24:19 GMT";
"Keep-Alive" = "timeout=5, max=100";
Server = "Apache/2.4.25 (Unix) PHP/5.6.30";
"X-Powered-By" = "PHP/5.6.30";
}
2019-05-20 19:24:19.606679+0800 NSURLSession[7076:151492] 代理方法返回的響應信息:{
status = 0;
total = 2;
user = {
name = jack;
password = 123;
};
}
2019-05-20 19:24:19.607593+0800 NSURLSession[7076:151550] Post請求返回的響應信息:{
status = 0;
total = 2;
user = {
name = jack;
password = 123;
};
}
2019-05-20 19:24:19.611332+0800 NSURLSession[7076:151552] Get請求返回的響應信息1:{
status = 0;
total = 2;
user = {
name = jack;
password = 123;
};
}
2019-05-20 19:24:19.613122+0800 NSURLSession[7076:151552] Get請求返回的響應信息2:{
status = 0;
total = 2;
user = {
name = jack;
password = 123;
};
}
demo鏈接
https://pan.baidu.com/s/1mZt_8GmV8ERKof7U6IMi5w
密碼:o4gz