NSURLConnection从入门到放弃
尽管NSURLConnection已经不建议使用了,iOS 7取而代之的是NSURLSession,但是本文依然打算剖析一下,其中一些思想还是值得学习一下,如果您不用NSURLConnection,并且也不打算尝试使用,可以跳过本文。
一、概念介绍
NSURLConnection是2003年随着第一版Safari的发布而发布的,它不单单是一个网络请求类,而是指代Foundation框架的URL系统中的一系列关联的组件:NSURLRequest、NSURLResponse、NSURLProtocol、NSHTTPCookieStorage、NSURLCredentialStorage以及同名类NSURLConnection。
1. 异步处理代理
其中,NSURLRequest被传递给NSURLConnection。被委托对象(遵守以前的非正式协议<NSURLConnectionDelegate>和<NSURLConnectionDataDelegate>)异步返回一个NSURLResponse以及包含服务器返回信息的NSData。
2. 请求策略
在一个请求被发送到服务器之前,系统会先查询共享的缓存信息,然后根据策略(policy)以及可用性(availability)的不同,一个已经被缓存的响应可能会被立即返回。如果没有缓存的响应可用,则这个请求将根据我们指定的策略来缓存它的响应以便将来的请求可以使用。
3. 认证策略
在把请求发送给服务器的过程中,服务器可能会发出鉴权查询(authentication challenge),这可以由共享的 cookie 或机密存储(credential storage)来自动响应,或者由被委托对象来响应。发送中的请求也可以被注册的NSURLProtocol对象所拦截,以便在必要的时候无缝地改变其加载行为。
4. 下载过程
NSURLConnection下载文件时,先是将整个文件下载到内存,然后再写入到沙盒,如果文件比较大,就会出现内存暴涨的情况。
二、使用步骤
请求步骤:
- 设置请求路径
- 创建请求对象(默认是GET请求,且已经默认包含了请求头)
- 发送网络请求
- 接收到服务器的响应后,解析响应体
0.常用代理介绍
/*
1.当接收到服务器响应的时候调用,该方法只会调用一次
第一个参数connection:监听的是哪个NSURLConnection对象
第二个参数response:接收到的服务器返回的响应头信息
*/
- (void)connection:(nonnull NSURLConnection *)connection didReceiveResponse:(nonnull NSURLResponse *)response
/*
2.当接收到数据的时候调用,该方法会被调用多次
第一个参数connection:监听的是哪个NSURLConnection对象
第二个参数data:本次接收到的服务端返回的二进制数据(可能是片段)
*/
- (void)connection:(nonnull NSURLConnection *)connection didReceiveData:(nonnull NSData *)data
/*
3.当服务端返回的数据接收完毕之后会调用
通常在该方法中解析服务器返回的数据
*/
-(void)connectionDidFinishLoading:(nonnull NSURLConnection *)connection
/*4.当请求错误的时候调用(比如请求超时)
第一个参数connection:NSURLConnection对象
第二个参数:网络请求的错误信息,如果请求失败,则error有值
*/
- (void)connection:(nonnull NSURLConnection *)connection didFailWithError:(nonnull NSError *)error
1. 各种方法请求
- 方法一:利用
sendSynchronousRequest发送GET请求,该请求是同步的
//1.确定请求路径
NSURL *url = [NSURL URLWithString:@""];
//2.创建一个请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//3.把请求发送给服务器
//sendSynchronousRequest 阻塞式的方法,会卡住线程
NSHTTPURLResponse *response = nil;
NSError *error = nil;
/*
第一个参数:请求对象
第二个参数:响应头信息,当该方法执行完毕之后,该参数被赋值
第三个参数:错误信息,如果请求失败,则error有值
*/
//该方法是阻塞式的,会卡住线程
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
// 对data进行处理
- 方法二:利用
sendAsynchronousRequest发送POST请求,该请求是异步的
//1.确定请求路径
NSURL *url = [NSURL URLWithString:@""];
//2.创建一个请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
// 2.1设置请求方式
// 注意: POST一定要大写
request.HTTPMethod = @"POST";
// 2.2设置请求体
// 注意: 如果是给POST请求传递参数: 那么不需要写?号
request.HTTPBody = [@"username=Mitchell&pwd=123456&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
//3.把请求发送给服务器,发送一个异步请求
/*
第一个参数:请求对象
第二个参数:回调方法在哪个线程中执行,如果是主队列则block在主线程中执行,非主队列则在子线程中执行
第三个参数: completionHandlerBlock块:接受到响应的时候执行该block中的代码
response:响应头信息
data:响应体
connectionError:错误信息,如果请求失败,那么该参数有值
*/
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * __nullable response, NSData * __nullable data, NSError * __nullable connectionError) {
//4.解析服务器返回的数据
NSString *str = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
//转换并打印响应头信息
NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
}];
- 方法三:通过设置代理,来处理请求响应或数据
// 第一种代理方式,自动发送请求
[[NSURLConnection alloc]initWithRequest:request delegate:self];
/*
第一个参数:请求对象
第二个参数:谁成为NSURLConnetion对象的代理
第三个参数:是否马上发送网络请求,如果该值为YES则立刻发送,如果为NO则不会发送网路请求
*/
NSURLConnection *conn = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
//在startImmediately为NO时,调用该方法控制网络请求的发送
[conn start];
// 第三种代理方式
//设置代理的第三种方式:使用类方法设置代理,会自动发送网络请求
NSURLConnection *conn = [NSURLConnection connectionWithRequest:request delegate:self];
//取消网络请求
//[conn cancel];
2. NSURLConnection 与 NSRunLoop 的关联使用
主要是区分 NSURLConnection 在主线程和子线程发送网络请求的区别
- 主线程
// 直接发送网络请求,发送是异步的,但是代理方法是在主线程中执行的
NSURL *url = [NSURL URLWithString:@"http://mvvideo1.meitudata.com/55d99e5939342913.mp4"];
NSURLRequest*request = [NSURLRequest requestWithURL:url];
//这里分两种方式发送请求
//2.1 直接发送网络请求是异步的,但是回调方法是在主线程中执行的
//[[NSURLConnection alloc]initWithRequest:request delegate:self];
// 如果按照如下设置,那么回调的代理方法也会运行在子线程中
NSURL*url = [NSURL URLWithString:@"http://mvvideo1.meitudata.com/55d99e5939342913.mp4"];
NSURLRequest*request = [NSURLRequest requestWithURL:url];
//2.2 设置回调方法也在子线程中运行
NSURLConnection*conn = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
[conn setDelegateQueue:[[NSOperationQueue alloc] init]];
[conn start];
- 子线程
因为 NSURLConnection 是局部变量,当我们创建的时候其实是会默认添加到当前的 RunLoop 中,如果是在主线程添加,主线程的 RunLoop 是默认有的,无须我们创建;然而如果在子线程中,是默认没有 RunLoop 和输入源的,所以需要给子线程手动添加 RunLoop。
调用start 方法时,如果没有 RunLoop ,会默认添加一个 RunLoop 到当前的线程中来,然后将connection加到runLoop中。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSRunLoop *loop = [NSRunLoop currentRunLoop];
[NSURLConnection connectionWithRequest:request delegate:self];
[loop run];
// 下面这样无法发送请求
[NSURLConnection connectionWithRequest:request delegate:self];
});
至此,NSURLConnection的简介结束,只是提供了最简单应用的参考,如有不足之处,请不吝指教。下一篇简介目前推荐应用的NSURLSession,敬请期待......
参考文档
http://www.jianshu.com/p/056b1817d25a
http://www.jianshu.com/p/982a3035c93a
http://www.jianshu.com/p/63e2ad28459f
http://www.jianshu.com/p/f291ee58c012
NSURLConnection从入门到放弃的更多相关文章
- CYQ.Data 从入门到放弃ORM系列:开篇:自动化框架编程思维
前言: 随着CYQ.Data 开始回归免费使用之后,发现用户的情绪越来越激动,为了保持这持续的激动性,让我有了开源的念头. 同时,由于框架经过这5-6年来的不断演进,以前发的早期教程已经太落后了,包括 ...
- [精品书单] C#/.NET 学习之路——从入门到放弃
C#/.NET 学习之路--从入门到放弃 此系列只包含 C#/CLR 学习,不包含应用框架(ASP.NET , WPF , WCF 等)及架构设计学习书籍和资料. C# 入门 <C# 本质论&g ...
- OpenStack从入门到放弃
OpenStack从入门到放弃 目录: 为何选择云计算/云计算之前遇到的问题 什么是云计算 云服务模式 云应用形式 传统应用与云感知应用 openstack及其相关组件介绍 flat/vlan/gre ...
- 绕过校园网的共享限制 win10搭建VPN服务器实现--从入门到放弃
一.开篇立论= =.. 上次说到博主在电脑上搭建了代理服务器来绕过天翼客户端的共享限制,然而经过实际测试还不够完美,所以本着生命不息,折腾不止的精神,我又开始研究搭建vpn服务器= =... (上次的 ...
- 《区块链:从入门到放弃》之obc安装步骤
obc安装步骤 朋友们可能会好奇,厨师不研究菜谱怎么改研究兵法了,哈哈,我原本是app出身,最近被安排去预研区块链和比特币技术,2个月下来,颇有斩获.期间得到IBM的CC同学指导我一步一步安装obc的 ...
- win10搭建代理服务器实现绕过校园网的共享限制--从入门到放弃
博主所在学校特别坑爹,校园网被电信一家垄断了,而且最恶心的还是电信要求一条网线只能供一台电脑上网,不许接路由器共享网络= =- (还有电信2M价格是380+每年,20m是500每年,而且网速都很慢= ...
- WPF从入门到放弃系列第二章 XAML
本文是作者学习WPF从入门到放弃过程中的一些总结,主要内容都是对学习过程中拜读的文章的整理归纳. 参考资料 XAML 概述 (WPF):https://msdn.microsoft.com/zh-cn ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃
1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...
- Android -- 带你从源码角度领悟Dagger2入门到放弃(二)
1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...
随机推荐
- (转载)IQ 16.0 SP02起支持从压缩文件直接装载数据到表中
参考文档: http://m.blog.chinaunix.net/uid-16765068-id-4405877.htmlhttp://www.cnblogs.com/lichmama/p/4103 ...
- Student implements java.io.Serializable
package JBJADV003; public class Student implements java.io.Serializable { private String name; priva ...
- usaco training 4.1.1 麦香牛块 题解
Beef McNuggets题解 Hubert Chen Farmer Brown's cows are up in arms, having heard that McDonalds is cons ...
- java for循环
publicclass Test2 { staticboolean foo(char c) { System.out.print(c); returntrue; ...
- jsonp的原理和实现
什么是JSONP? javascript高级程序设计中是这样介绍jsonp的: jsonp是JSON with padding(填充式JSON或参数式JSON )的简写,是应用JSON的一种新方法,在 ...
- Sublime Text中安装插件来实现px与rem间的换算
今天在群里无意中看到了群友分享的一篇关于移动端的文章.里面其他内容我倒不大感兴趣,反而是rem让我提起了兴趣. 首先来谈一下rem,rem是CSS3中新增加的一个单位值,它和em单位一样,都是一个相对 ...
- 详解equals()方法和hashCode()方法
前言 Java的基类Object提供了一些方法,其中equals()方法用于判断两个对象是否相等,hashCode()方法用于计算对象的哈希码.equals()和hashCode()都不是final方 ...
- PHP树结构,实现无限分级
一.从数据库查出来的数据需要id.parentid.level. id唯一识别栏目,parentid为该栏目所属父类id,level标示该栏目是几级栏目.以下代码就可以实现一个简单的树结构. publ ...
- C++第四篇--重载_指针_引用
C++第四篇--重载_指针_引用 1. 基础知识 重载:函数名相同,根据参数不同(类型.数量.顺序不同)调用同名函数 指针和引用:引用就是别名,引用时必须初始化,引用你定义的变量. int a; in ...
- iOS App签名的原理
前言 相信很多同学对于iOS的真机调试,App的打包发布等过程中的各种证书.Provisioning Profile. CertificateSigningRequest.p12的概念是模糊的,导致在 ...