网络请求是App获取远程数据和资源的一种普遍且重要的方法,目前我们在 App Store 上看到的绝大部分应用都会与网络进行数据交互,所以网络请求在应用开发中,也是绕不过去的重要一环。这里就简单记录一下使用原生方法进行简单的请求必应壁纸的信息。
API如下:https://bing.creepersan.com/document
一个简单的网络请求
在iOS开发中,发送一个简单的请求需要3个组件。
- NSURL:统一资源定位符
- NSURLRequest:请求参数的定义
- NSURLSession:用于完成网路请求相关操作资源数据
当我们需要获取网络上的数据的时候,会把请求的地址封装成为NSURL。然后在NSURL的基础之上,会一并的把一些请求参数、设置(GET、POST请求方法、请求参数、超时时间之类的)封装成一个NSURLRequest请求。拿到这个请求后,调用系统提供的NSURLSession相关函数就能发送到服务器上并接受对应的返回数据。
NSURL
Uniform Resource Locator,统一资源定位符。是一个用于定位一个资源位置的协议(不仅仅是网络请求,本地文件之类的也可以用他描述)。其格式打入如下
[协议类型]://[服务器地址]:[端口号]/[资源层级unix路径]/[文件名]?[查询参数]#[片段ID]
我们在浏览器上输出的那些地址,其实都是符合URL规范的字符串。也就是说,我们接下来要发送的网络请求地址,也是符合URL协议的规范的。
NSURL,就是iOS平台上封装好的一套URL规范,其内部对URL进行了各部分的划分,我们就能通过这个类获得URL地址中的各部分信息了
我们也能在NSURL的头文件中找到这些数据的定义
通过这个封装,我们就能免去一些列的解析逻辑,直接从里面取出对应的数据即可
可以通过 requestWithURL
函数进行请求对象的生成
NSURLRequest
有了上面提及到的NSURL后,我们就能定位我们想要获取到的资源的路径了。但是光知道一个路径,还不足以把对应的数据取到手。URL只是Http请求中的其中一个重要数据,但是并不是所有数据。我们还需要更多的信息,比如说 请求方法(GET、POST之类的),请求参数,Header,Cookie之类的信息。而且,对于一些请求可能还会后更多自定义的设置(例如指定请求的超时时间增等)。
所以,为了把这些数据、设置和NSURL打包为一个整体,NSURLRequest便由此而来。
NSURLRequst对象就代表着一个请求,包含NSURL对象、请求方法、请求头、请求体等等信息
NSURLSession
有了前面的请求后,便有了发起请求的数据了。要发送这个请求并获得数据进行处理,可以通过NSURLSession处理(以前是NSURLConnection,现已弃用)。其作用主要有
- 负责接收、发送和处理请求
- 一个Session可以创建多个请求
- 可以根据不同的配置创建多个Session
- 对Request进行封装处理、控制获取请求的状态、开始、取消、进度
值得注意的是,在使用NSURLSession的过程中不要每一个请求都创建一个NSURLSession。应该相同配置和策略的请求使用一个NSURLSession,因为系统会对这个NSURLSession进行统一的管理
组织结构如下图
要创建一个NSURLSession,我们可以通过这两个函数进行创建自定义的配置和策略的对象
我们可以注意到,其配置都是存放在 NSURLSessionConfiguration 中,其内部主要提供了这些设置
- 超时时间
- cookie缓存策略
- 最大并发数、是否支持蜂窝数据
- 其他网络行为的行为策略
- 根据Configuration的不同,提供默认、狗太以及自定义
如果我们没有什么特殊的要求的话,也可以使用系统提供的默认的NSURLSession——sharedSession
获取到了NSURLSession后,我们需要把NSURLRequest抓换为对应的Task,然后通过操作Task进行数据的请求的加载,并通过delegate获得不同阶段网络请求的回调。而根据不同的请求策略,可以分为以下四种Task
- dataTask:处理json之类的简单的数据流
- downloadTask:大数据下载,断点续存和下载进度等
- uploadTask:数据上传
- streamTask:数据流
对应的task的转换,可以通过这些函数进行转换
对应Task的继承关系可以参考下图
dataTask有以下几种状态
task创建时,默认为suspend状态,当设置为resume后,则进行请求
请求完成后,获取对应的请求的阶段以及对应的数据有2种方式获取到
一种是通过block的方式,在请求时传入block,那么在不同阶段的数据回调时,就会自动执行block中的逻辑。
另外一种是通过delegate的方式,在请求的阶段中,回调到delegate中对数据进行处理
需要注意的是,新版本的iOS默认是支持https请求但不支持http请求的,如果需要支持,则需要在info.plist中加入这段内容
发起网络请求
根据上面的描述,要发起一个网络请求,首先得有一个NSURL,要创建一个NSURL,我们可以从字符串中创建一个NSURL
NSString *urlString = @"https://bing.creepersan.com/api/v1/url?page=1&count=12";
NSURL *url = [NSURL URLWithString:urlString];
拿到了对应的NSURL后,继续用它生成NSURLRequest
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
不过 NSURLRequest requstWithURL
拿到的是只读的NSURLRequest,其内部的一些值是不可以进行设置的,如需进行设置,也可以通过 NSMutableURLRequest
进行请求的生成
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
[request setURL:url];
[request setHTTPMethod:@"POST"];
[request setHTTPBody:nil];
有了请求的数据与配置后,就是通过NSURLSession进行请求了
接口返回的数据是简单的JSON字符串,因此可以使用默认的session创建dataTask
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:urlRequest];
然后就是请求网络并获取回调了
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
整体代码如下所示
- (void)viewDidLoad {
[super viewDidLoad];
NSString *urlString = @"https://bing.creepersan.com/api/v1/url?page=1&count=12";
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *task = [session dataTaskWithRequest:urlRequest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"%@", [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
}];
[task resume];
}
编译运行,可以看到控制台输出了接口返回的数据
网络请求完成
本文由 CreeperSan 创作,采用 知识共享署名4.0
国际许可协议进行许可
本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名
最后编辑时间为: Sep 7,2020