iOS网络请求
本文讲解了用iOS原生套类URLSession实现网络请求的方式方法。
本文阅读大概需要10分钟左右
HTTP协议
网络数据通信需要遵守数据传输协议,几乎所有的客户端服务器网络通信都是基于HTTP协议的。关于HTTP协议妹子就不废话了,网上没有10000也有5000篇这种文章的介绍,这里推荐一篇速览文章,短小易懂快速理解HTTP协议。
URLSession
做iOS开发的肯定都知道URLSession,但是大家天天用网络框架估计都对URLSession有点模糊了,妹子这里用URLSession写两个请求,帮大家复习下这个套类是怎样做GET
&POST
请求的,另外关URLSession的文章详解的文章有很多,可以去详细了解下。
GET请求
妹子在这里申请了一个聚合数据的账号做测试用,请求的常用快递查询接口,大家如果想做测试可以去自己申请一个
//配置config选项
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 30.f; //设置session请求超时30s
//使用config初始化一个 URLSession对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
//常用快递查询 GET请求
/**
参数:
key:申请的聚合数据的key
com:快递缩写
no:快递单号
type:返回数据格式
*/
NSURL *url = [NSURL URLWithString:@"https://v.juhe.cn/exp/index?key=7ea4e3ec1f227104b8f35ed50bcd6797&com=yt&no=802616352006034501&dtype=json"];
//这里妹子用了session生成datatask任务的获取返回数据的方式callback方式,
//当然以可以使用代理方式的API接口获取数据,下面的POST请求会使用代理方式来获取数据
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//请求相应的rawData数据,是NSData的二进制数据
NSLog(@"\ndata=%@\n",data);
//需要自己做json解析,解析成OC数据结构
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers | NSJSONReadingAllowFragments error:nil];
NSLog(@"response content dic=%@\n",dic);
//HTTP相应数据
NSLog(@"response=%@\n",response);
//请求发生错误时候返回的数据
NSLog(@"error=%@",error);
}];
//开启datatask任务
[dataTask resume];
下面是Response的content内容
response content dic={
"error_code" = 0;
reason = "\U67e5\U8be2\U6210\U529f";
result = {
com = yt;
company = "\U5706\U901a";
list = (
{
datetime = "2018-11-12 11:51:34";
remark = "\U5e7f\U4e1c\U7701\U5e7f\U5dde\U5e02\U9ec4\U57d4\U533a\U4e1c\U533a\U6c38\U548c\U516c\U53f8\U53d6\U4ef6\U4eba: \U9ec4\U4f1f\U94a6\Uff0813602438384\Uff09 \U5df2\U6536\U4ef6";
zone = "";
},
{
datetime = "2018-11-12 15:30:17";
remark = "\U5feb\U4ef6\U5df2\U53d1\U5f80 \U5e7f\U5dde\U8f6c\U8fd0\U4e2d\U5fc3";
zone = "";
},
{
datetime = "2018-11-12 22:33:51";
remark = "\U5feb\U4ef6\U5df2\U5230\U8fbe \U5e7f\U5dde\U8f6c\U8fd0\U4e2d\U5fc3";
zone = "";
},
{
datetime = "2018-11-12 23:40:29";
remark = "\U5feb\U4ef6\U5df2\U53d1\U5f80 \U5317\U4eac\U8f6c\U8fd0\U4e2d\U5fc3";
zone = "";
},
{
datetime = "2018-11-14 19:09:38";
remark = "\U5feb\U4ef6\U5df2\U5230\U8fbe \U5317\U4eac\U8f6c\U8fd0\U4e2d\U5fc3";
zone = "";
},
{
datetime = "2018-11-15 09:04:03";
remark = "\U5feb\U4ef6\U5df2\U53d1\U5f80 \U5317\U4eac\U5e02\U671d\U9633\U533a\U89c2\U6e56\U516c\U53f8";
zone = "";
}
);
no = 802616352006034501;
status = 0;
};
resultcode = 200;
}
下面是HTTP Response 的返回头以及状态码内容,封装的是HTTP协议中规定的返回响应的内容
{ URL: https://v.juhe.cn/exp/index?key=7ea4e3ec1f227104b8f35ed50bcd6797&com=yt&no=802616352006034501&dtype=json } { Status Code: 200, Headers {
Connection = (
"keep-alive"
);
"Content-Type" = (
"application/json;charset=utf-8"
);
Date = (
"Thu, 15 Nov 2018 03:07:01 GMT"
);
Etag = (
02132b8fec79c49b795f7726ed238b59
);
"Set-Cookie" = (
"aliyungf_tc=AQAAAOfGX3hMNgAAy0VuJIr54XXOX7Kn; Path=/; HttpOnly"
);
"Transfer-Encoding" = (
Identity
);
} }
POST请求
妹子下面演示下用POST请求请求同一个接口
//构造POST请求需要使用NSMutableURLRequest 来封装HTTP Method方法,body请求体
NSMutableURLRequest *request = [[NSMutableURLRequest alloc]initWithURL:[NSURL URLWithString:@"https://v.juhe.cn/exp/index"]];
//设置请求方式POST,妹子这里猜测默认的请求方式应该是GET不然上面的GET方法也不可能请求成功
request.HTTPMethod = @"POST";
//设置请求头部内容,只设置请求content数据格式,其他请求头部内容使用默认的
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
//构造POST请求体 参数还是上面那几个参数 body是二进制NSData类型
//构造参数
/**!!!
NSString *param = @{@"key" : @"7ea4e3ec1f227104b8f35ed50bcd6797",
@"com" : @"yt",
@"no" : @"802616352006034501",
@"dtype" : @"json"
};
NSData *paramData = [NSJSONSerialization dataWithJSONObject:param options:NSJSONWritingPrettyPrinted error:nil];
妹子在这里试过类似于dicjson序列化为NSData的方式但是好像这样行不通请求参数错误
后来调研http请求POST请求的请求体也是用字符串拼接,参数之间用&分开的方式
**/
NSString *paramStr = @"key=7ea4e3ec1f227104b8f35ed50bcd6797&com=yt&no=802616352006034501&dtype=json";
//使用utf-8编码
NSData *paramData = [paramStr dataUsingEncoding:NSUTF8StringEncoding];
//设置http body
[request setHTTPBody:paramData];
//这里使用URLSession 的代理回调处理请求的响应
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 30.f;
//设置session的代理方法 代理方法在哪个线程里面处理
NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//创建task
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
//执行task
[dataTask resume];
回调的代理方法在 NSURLSessionDataDelegate 协力里面
#pragma mark - NSURLSessionDataDelegate
//step1.接受到服务器相应 该方法会先被调用
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{
NSLog(@"response = %@\n",response);
/**
判定该次任务是否继续执行,或者转化为其他类型的任务
typedef NS_ENUM(NSInteger, NSURLSessionResponseDisposition) {
NSURLSessionResponseCancel = 0, //取消本次task任务
NSURLSessionResponseAllow = 1, //本次task任务继续
NSURLSessionResponseBecomeDownload = 2, //转变本次dataTask任务为一个downloadTask下载任务
NSURLSessionResponseBecomeStream //转变本次dataTask任务为一个StreamTask流任务
} NS_ENUM_AVAILABLE(NSURLSESSION_AVAILABLE, 7_0);
*/
//允许本次task继续执行
completionHandler(NSURLSessionResponseAllow);
}
//setp2.数据传输的过程中该方法会被调用 如果返回数据特别长,该方法会被多次调用
// @property(nonatomic,strong)NSMutableData *receiveData; 在上面事先声明好NSMutableData数据拼接返回的data数据
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data{
NSLog(@"ReceiveData = %@\n", data);
//拼接返回的数据
[self.receiveData appendData:data];
}
//step3:数据传输完成最后该方法会被调用 不管最后该次请求成功或者失败该方法都会调用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
if(error){
// 请求失败
NSLog(@"error = %@\n",error);
}else{
// 请求成功
//解析返回的数据
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:self.receiveData options:NSJSONReadingMutableContainers | NSJSONReadingAllowFragments error:nil];
NSLog(@"response content = %@",dic);
}
}
总结
客户端的业务80%都是GET POST请求,下一篇妹子会仔细分析下AFNetworking这个协议框架,因为貌似绝大多数项目都用这个框架,这一篇算做了一个铺垫吧。