简介
在iOS中,常见的发送HTTP请求的方案有
苹果原生(自带)
NSURLConnection:用法简单,最古老最经典最直接的一种方案【坑比较多】
NSURLSession:功能比NSURLConnection更加强大,苹果目前比较推荐使用这种技术【2013推出,iOS7开始出的技术】
CFNetwork:NSURL*的底层,纯C语言
第三方框架
ASIHttpRequest:外号“HTTP终结者”,功能极其强大,可惜早已停止更新
AFNetworking:简单易用,提供了基本够用的常用功能,维护和使用者多
MKNetworkKit:简单易用,产自三哥的故乡印度,维护和使用者少
建议
为了提高开发效率,企业开发用的基本是第三方框架
请求
HTTP协议规定:1个完整的由客户端发给服务器的HTTP请求中包含以下内容
请求头:包含了对客户端的环境描述、客户端请求信息等
GET /minion.png HTTP/1.1 // 包含了请求方法、请求资源路径、HTTP协议版本
Host: 120.25.226.186:32812 // 客户端想访问的服务器主机地址
User-Agent: Mozilla/5.0 // 客户端的类型,客户端的软件环境
Accept: text/html, */* // 客户端所能接收的数据类型
Accept-Language: zh-cn // 客户端的语言环境
Accept-Encoding: gzip // 客户端支持的数据压缩格式
请求体:客户端发给服务器的具体数据,比如文件数据(POST请求才会有)
响应
客户端向服务器发送请求,服务器应当做出响应,即返回数据给客户端
HTTP协议规定:1个完整的HTTP响应中包含以下内容
响应头:包含了对服务器的描述、对返回数据的描述
HTTP/1.1 200 OK // 包含了HTTP协议版本、状态码、状态英文名称
Server: Apache-Coyote/1.1 // 服务器的类型
Content-Type: image/jpeg // 返回数据的类型
Content-Length: 56811 // 返回数据的长度
Date: Mon, 23 Jun 2014 12:54:52 GMT // 响应的时间
响应体:服务器返回给客户端的具体数据,比如文件数据
修改请求头
NSURL * url = [NSURL URLWithString:@"https://m.baidu.com"];
//2.request,向服务器提供附加信息,可变的请求
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
//告诉服务器一些附加信息
//User-Agent 就是告诉服务器客户端的类型:iPhone
//forHTTPHeaderField 所有访问服务器前,要额外告诉服务器的附加信息,都是通过这个字段来设置的!
[request setValue:@"iPhone AppleWebKit" forHTTPHeaderField:@"User-Agent"];
//3.连接服务器
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//将二进制数据转换为字符串
NSString * html = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",html);
//让webView 显示html
[self.myWebView loadHTMLString:html baseURL:nil];
}];
NSURLRequest 缓存策略
sendAsynchronousRequest 参数解析
- (void)viewDidLoad {
[super viewDidLoad];
// 0.NSData 方法 在实际开发中用不到!
/* 因为:
- 默认超时时长 60s,没有办法修改.而且没有缓存策略
- dataWithContentsOfURL 是同步方法 (会阻塞线程)
- 没有错误处理机制!
*/
// NSData * data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://127.0.0.1/demo.json"]];
// NSString * json = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
//1.url
NSURL * url = [NSURL URLWithString:@"http://127.0.0.1/demo.json"];
//2.request
/**
* timeoutInterval : 超时时长
一般在实际开发中建议: 15--30秒 太短了可能服务器来不及做出响应,太长了用户等待太久,影响体验
- SDWebImage 默认时长 15s
- AFNetworking 默认时长 60s
cachePolicy:缓存策略
NSURLRequestUseProtocolCachePolicy = 0
默认缓存策略
NSURLRequestReload(刷新)Ignoring(忽略)Local(本地)Cache(缓存)Data = 1
忽略本地缓存数据,直接加载网络数据,每次都是"最新数据"
应用场景:数据变化非常频繁的APP 股票,彩票
*** 以下两个选项,专门用于离线浏览的,建议结合 Reachability 框架联合使用
- 如果用户当前没有网络,就使用本地缓存策略
- 如果有网络就用默认缓存策略
NSURLRequestReturnCacheDataElseLoad = 2 返回缓存数据,如果没有缓存从服务器加载
NSURLRequestReturnCacheDataDontLoad = 3 返回缓存数据,如果没有缓存,就空着!!!
*/
NSURLRequest * request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:15.0];
//3.发送请求 -- 异步发送,错误处理机制!
/**
* 1.request - 索要资源的请求
* 2.queue - 调度任务的队列
指定调度回调代码块的队列!
- 主队列,回调的代码块在主线程上执行
- 新建队列,就会在其他线程执行回调代码
如何选择: 是否需要更新UI
* 3.block - 回调代码块,在网络请求结束后执行!
3.1 response(NSHTTPURLResponse):服务器的响应
URL 服务器返回的URL,绝大部分和请求的URL是一样的,有的时候不一样."重定向"
MIMEType 二进制数据的文件类型.服务器会告诉客户端,可以使用什么软件,打开二进制数据!
expectedContentLength 下载文件的长度
textEncodingName 文本编码名称,大多是UTF8
suggestedFilename 服务器建议保存的文件名称
statusCode 状态码 2XX 3XX 重定向 4XX客户端错误 5XX 服务器错误
allHeaderFields 所有响应头的内容
3.2 data:数据实体,程序员开发最关注的
3.3 connectionError:错误处理
注意:有一种情况是没有错误,也没有数据!!(本来应该有数据)
if(connectionError || data == nil){
NSLog(@"你的网络不给力,请稍后再试!!!");
}
*/
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
NSLog(@"%@",response);
NSString * json = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"%@",json);
}];
NSLog(@"同步请求方式(sendSynchronousRequest),会阻塞,执行完后才执行到此行");
}
关于枚举 ( NS_ENUM & NS_OPTIONS )
C语言定义枚举的类型,枚举的数据类型不确定的,会默认的使用 int
iOS 6.0 之后推出两个宏 NS_ENUM & NS_OPTIONS
NS_ENUM 定义枚举的同时,指定数据的类型
NS_OPTIONS 定义的枚举是位移的,可以用按位或 来设置数值(设置多个值)
如果看到NS_OPTIONS 定义的枚举,直接传入0 作为参数 标示什么附加操作也不做.效率最高!
JSON反序列化 : JSONObjectWithData参数解析
NSURL * url = [NSURL URLWithString:@"http://192.168.31.180/demo.json"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//解析数据
// 二进制数据-->OC对象 : 反序列化
//[NSJSONSerialization JSONObjectWithData:] 能够将网络返回的二进制数据转换成为字典或者数组
/*
一个JSON对象应该具有以下属性
- Top level object is an NSArray or NSDictionary
顶级节点是一个NSArray 或者 NSDictionary
- All objects are NSString, NSNumber, NSArray, NSDictionary, or NSNull
所有的对象必须是 NSString, NSNumber, NSArray, NSDictionary, or NSNull
- All dictionary keys are NSStrings
所有的字典的KEY 必须是 NSString
- NSNumbers are not NaN or infinity
NSNumber 不能是无理数或者空
*/
/* options :
NSJSONReadingMutableContainers 容器节点是可变的
NSJSONReadingMutableLeaves 子节点是可变的
NSJSONReadingAllowFragments 允许顶级节点不是 NSArray 或者 NSDictionary
*/
id result = [NSJSONSerialization JSONObjectWithData:data options:1 error:NULL];
//JSON 的解析并不是表面上那么简单!
//出现过的JSON解析的三方框架 JSONKit SBJson ToudchJSON
NSLog(@"%@",[result class]);
for (NSDictionary * dict in result) {
NSLog(@"==> %@",dict);
}
}];
plist 反序列化 : NSPropertyListSerialization
//plist 很少用于传输网络数据,只是苹果使用的比较多
NSURL * url = [NSURL URLWithString:@"http://192.168.31.180/messages.plist"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
//NSJson(JSON)Serialization(序列化)
//NSPropertyList(属性列表)Serialization(序列化)
/*
NSPropertyListImmutable 不可变
NSPropertyListMutableContainers 容器可变
NSPropertyListMutableContainersAndLeaves 容器和子节点可变的
*/
id result = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:NULL error:NULL];
NSLog(@"%@ %@",result,[result class]);
}];
网友评论