尽管NSURLConnection已经不建议使用了,iOS 7取而代之的是NSURLSession,但是本文依然打算剖析一下,其中一些思想还是值得学习一下,如果您不用NSURLConnection,并且也不打算尝试使用,可以跳过本文。

一、概念介绍

NSURLConnection是2003年随着第一版Safari的发布而发布的,它不单单是一个网络请求类,而是指代Foundation框架的URL系统中的一系列关联的组件:NSURLRequestNSURLResponseNSURLProtocolNSHTTPCookieStorageNSURLCredentialStorage以及同名类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从入门到放弃的更多相关文章

  1. CYQ.Data 从入门到放弃ORM系列:开篇:自动化框架编程思维

    前言: 随着CYQ.Data 开始回归免费使用之后,发现用户的情绪越来越激动,为了保持这持续的激动性,让我有了开源的念头. 同时,由于框架经过这5-6年来的不断演进,以前发的早期教程已经太落后了,包括 ...

  2. [精品书单] C#/.NET 学习之路——从入门到放弃

    C#/.NET 学习之路--从入门到放弃 此系列只包含 C#/CLR 学习,不包含应用框架(ASP.NET , WPF , WCF 等)及架构设计学习书籍和资料. C# 入门 <C# 本质论&g ...

  3. OpenStack从入门到放弃

    OpenStack从入门到放弃 目录: 为何选择云计算/云计算之前遇到的问题 什么是云计算 云服务模式 云应用形式 传统应用与云感知应用 openstack及其相关组件介绍 flat/vlan/gre ...

  4. 绕过校园网的共享限制 win10搭建VPN服务器实现--从入门到放弃

    一.开篇立论= =.. 上次说到博主在电脑上搭建了代理服务器来绕过天翼客户端的共享限制,然而经过实际测试还不够完美,所以本着生命不息,折腾不止的精神,我又开始研究搭建vpn服务器= =... (上次的 ...

  5. 《区块链:从入门到放弃》之obc安装步骤

    obc安装步骤 朋友们可能会好奇,厨师不研究菜谱怎么改研究兵法了,哈哈,我原本是app出身,最近被安排去预研区块链和比特币技术,2个月下来,颇有斩获.期间得到IBM的CC同学指导我一步一步安装obc的 ...

  6. win10搭建代理服务器实现绕过校园网的共享限制--从入门到放弃

    博主所在学校特别坑爹,校园网被电信一家垄断了,而且最恶心的还是电信要求一条网线只能供一台电脑上网,不许接路由器共享网络= =- (还有电信2M价格是380+每年,20m是500每年,而且网速都很慢= ...

  7. WPF从入门到放弃系列第二章 XAML

    本文是作者学习WPF从入门到放弃过程中的一些总结,主要内容都是对学习过程中拜读的文章的整理归纳. 参考资料 XAML 概述 (WPF):https://msdn.microsoft.com/zh-cn ...

  8. Android -- 带你从源码角度领悟Dagger2入门到放弃

    1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...

  9. Android -- 带你从源码角度领悟Dagger2入门到放弃(二)

    1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...

随机推荐

  1. python - bilibili(四)抓包数据乱码

    上一篇文章中不知道大家发现端倪木有,两张照片对比很明显发现第一张是信息很明显的,第二张是乱码的. 为什么会出现这种情况?细心的童鞋可能发现是我们发送给服务器的请求连接的数据不同: 第一张图的信息是{& ...

  2. 使用C#创建简单的WCF服务

    一.开发环境 操作系统:Windows 10 开发环境:VS2015 编程语言:C# IIS版本:10.0.0.0 二.添加WCF服务.Internet Information Services(II ...

  3. IE事件处理

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  4. CJOJ 1308 【HNOI 2002 】营业额统计 / CodeVS 1296 营业额统计(STL,二分)

    CJOJ 1308 [HNOI 2002 ]营业额统计 / CodeVS 1296 营业额统计(STL,二分) Description Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一 ...

  5. Nginx 502 Bad Gateway

    今天安装完php环境以后,出现这个问题,排查步骤如下: ps -ef|grep php-fpm 发现没有安装php-fpm 然后直接安装php-fpm yum -y install php-fpm 安 ...

  6. docker学习笔记--重基础使用

    最近一直在研究Elasticsearch,后来部门的同事遇到了一个docker集群的未授权访问漏洞,于是稍微看了一下docker进行了一下基本的入门,本文把自己学习docker的过程进行了一个详细的记 ...

  7. java Script 用if else 实现从大到小指定输出,升序排列

    我只是一个小白 各位大神看到不要介意 var a = Number(prompt("请输入你需要排列的第一个数字")) var b = Number(prompt("请输 ...

  8. scroll事件实现监控滚动条并分页显示示例(zepto.js )

    今天做了一个类似于手机端京东首页的页面,效果图如下: 刷新页面的时候,标题栏(也就是搜索栏),背景是透明的,当我们往下滑的时候,可以改变标题栏的背景透明度(渐变效果): 当标题栏滑过轮播图后,透明度就 ...

  9. poj_1845: Sumdiv

    题目链接 先将A^B分解质因数,可以通过先分解A,再把对应的幂次*B.之后用下面这个式子求解就可以了 #include<vector> #include<iostream> u ...

  10. 最短路径之Dijkstra算法和Floyd-Warshall算法

    最短路径算法 最短路径算法通常用在寻找图中任意两个结点之间的最短路径或者是求全局最短路径,像是包括Dijkstra.A*.Bellman-Ford.SPFA(Bellman-Ford的改进版本).Fl ...