IOS网络篇1之截取本地URL请求(NSURLProtocol)
本文转载至 http://blog.csdn.net/u014011807/article/details/39894247
NSURLProtocol 是iOS中非常重要的一个部分,我们经常会在以下地方用到它:
(1)网络请求代理转发(FQ 网络加速等)
(2)离线缓存策略
总之,只要是需要对本地的URL请求进行截获的,我们都需要使用这个东东。
IOS中我们经常使用的网络请求NSURLConnection以及WebView的页面加载都会被NSURLProtocol截获,因此这个部分的核心就是如何来用这个部分:
下面我将根据使用的步骤来描述NSURLProtocol的使用过程:
最终运行结果:
(1)首先我们需要创建一个类,继承NSURLProtocol
并且实现代理继承:
@interfaceMyURLProtocol () <NSURLConnectionDelegate>
@end
(2)注册这个协议
一般情况下,这个协议在AppDelegate文件中注册:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[NSURLProtocol registerClass:[MyURLProtocolclass]];
// Override point for customization after application launch.
returnYES;
}
下面就可以使用这个东东了
(3)下面准备好一段WebView的页面加载代码,这个太简单了,不详细说了,给一个参考代码:
- (void) sendRequest {
NSString *text =self.textField.text;
if (![textisEqualToString:@""]) {
NSURL *url = [NSURLURLWithString:text];
NSURLRequest *request = [NSURLRequestrequestWithURL:url];
[self.webView loadRequest:request];
}
}
(4)可以正常的使用这个NSURLProtocol只需要简单的使用下面9个方法,这九个方法是这个协议可以实现的最基本和最重要的几个方法,当然它还有很多高级的功能,这里就不一一介绍了。
最重要的9个方法如下:
<1>
@method:创建NSURLProtocol实例,NSURLProtocol注册之后,所有的NSURLConnection都会通过这个方法检查是否持有该Http请求。
@parma :
@return: YES:持有该Http请求NO:不持有该Http请求
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
#pragma mark --NSURLProtocol Hold RelevantMethod 4个方法
<2-5>
@method: NSURLProtocol抽象类必须要实现。通常情况下这里有一个最低的标准:即输入输出请求满足最基本的协议规范一致。因此这里简单的做法可以直接返回。一般情况下我们是不会去更改这个请求的。如果你想更改,比如给这个request添加一个title,组合成一个新的http请求。
@parma :本地HttpRequest请求:request
@return:直接转发
+ (NSURLRequest*)canonicalRequestForRequest:(NSURLRequest *)request
@method: NSURLProtocol缓存系统设置:如果有两个URL请求,并且他们是相等的,那么这里可以使用相同的缓存空间
@parma :本地HttpRequest请求:request
@return:
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest*)b
@method:获取网站上的数据建立connect连接
@parma :
@return:
- (void)startLoading
@method:当前Connection连接取消的时候被调用。尤其要注意这个StopLoading方法,在本地NSURLRequest初始化的时候,有一个超时时间,在低速网络下,有可能页面还没来得及加载完,这个StopLoading方法就被调用了。
@parma :
@return:
- (void)stopLoading
<6-9>接收数据
#pragma mark --NSURLProtocol Delegate 4个方法
- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection*)connection didReceiveData:(NSData*)data
- (void)connectionDidFinishLoading:(NSURLConnection*)connection
- (void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
注意这里的方法中:
canInitWithRequest 会创建一个实例,YES时候,然后继续调用startLoading。这里会继续调用canInitWithRequest。陷入死循环,因此这里我们常用的做法是设置一个[NSURLProtocolsetProperty:@YESforKey:@"MyURLProtocolHandledKey"inRequest:newRequest];
这样就可以避免程序陷入死循环。
(5)下面给出一段参考代码:
@implementation MyURLProtocol
/**
@method: 创建NSURLProtocol实例,NSURLProtocol注册之后,所有的NSURLConnection都会通过这个方法检查是否持有该Http请求。
@parma :
@return: YES:持有该Http请求 NO:不持有该Http请求
*/
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
staticNSUInteger requestCount =0;
NSLog(@"Request #%u: URL = %@", requestCount++, request);
if([NSURLProtocolpropertyForKey:@"MyURLProtocolHandledKey"inRequest:request]) {
returnNO;
}
returnYES;
}
#pragma mark --NSURLProtocol Hold Relevant Method
/**
@method: NSURLProtocol抽象类必须要实现。通常情况下这里有一个最低的标准:即输入输出请求满足最基本的协议规范一致。因此这里简单的做法可以直接返回。一般情况下我们是不会去更改这个请求的。如果你想更改,比如给这个request添加一个title,组合成一个新的http请求。
@parma : 本地HttpRequest请求:request
@return: 直接转发
*/
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest*)request {
return request;
}
/**
@method: NSURLProtocol缓存系统设置:如果有两个URL请求,并且他们是相等的,那么这里可以使用相同的缓存空间
@parma : 本地HttpRequest请求:request
@return:
*/
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
return [superrequestIsCacheEquivalent:atoRequest:b];
}
- (void)startLoading {
NSMutableURLRequest *newRequest = [self.requestmutableCopy];
[NSURLProtocolsetProperty:@YESforKey:@"MyURLProtocolHandledKey"inRequest:newRequest];
self.connection = [NSURLConnectionconnectionWithRequest:newRequestdelegate:self];
}
/**
@method: 当前Connection连接取消的时候被调用
@parma :
@return:
*/
- (void)stopLoading {
[self.connectioncancel];
self.connection =nil;
}
#pragma mark --NSURLProtocol Delegate
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.clientURLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.clientURLProtocol:selfdidLoadData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[self.clientURLProtocolDidFinishLoading:self];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
[self.clientURLProtocol:selfdidFailWithError:error];
}
@end
IOS网络篇1之截取本地URL请求(NSURLProtocol)的更多相关文章
- iOS网络篇
iOS网络请求三步: 1.新建URL连接 2.新建请求(请求新建的URL连接) 3.建立连接. 然后就可以获取数据了. 一.同步GET请求方法 -(void)synchronizationGet { ...
- ios -网络加载json和本地加载json
1网络加载json的时候,要在模型的实现文件里写: - (void)setValue:(id)value forKey:(NSString *)key { } 2本地加载json的时候,要在模型的实现 ...
- IOS网络第二天 - 01-基本的HTTP请求
***************** #import "HMViewController.h" #import "MBProgressHUD+MJ.h" @int ...
- IOS网络第一天-01基本的HTTP请求
*************************** #import "HMViewController.h" #import "MBProgressHUD+MJ.h& ...
- iOS网络相关零散知识总结
iOS网络相关零散知识总结 1. URL和HTTP知识 (1) URL的全称是Uniform Resource Locator(统一资源定位符). URL的基本格式 = 协议://主机地址/路径 ...
- iOS开发网络篇—搭建本地服务器
iOS开发网络篇—搭建本地服务器 一.简单说明 说明:提前下载好相关软件,且安装目录最好安装在全英文路径下.如果路径有中文名,那么可能会出现一些莫名其妙的问题. 提示:提前准备好的软件 apache- ...
- iOS开发网络篇—HTTP协议
iOS开发网络篇—HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...
- iOS开发网络篇—文件的上传
iOS开发网络篇—文件的上传 说明:文件上传使用的时POST请求,通常把要上传的数据保存在请求体中.本文介绍如何不借助第三方框架实现iOS开发中得文件上传. 由于过程较为复杂,因此本文只贴出部分关键代 ...
- 02.iOS开发网络篇—HTTP协议
iOS开发网络篇—HTTP协议 说明:apache tomcat服务器必须占用8080端口 一.URL 1.基本介绍 URL的全称是Uniform Resource Locator(统一资源定位符) ...
随机推荐
- SpagoBI 教程 Lesson 4: BIRT Reports
SpagoBI Lesson 4: BIRT Reports BIRT BIRT is the acronym for Business Intelligence and Reporting Tool ...
- PhotoshopCS6常用快捷键速查
写此文的起因:这学期开了一门多媒体技术课程,主要学习Photoshop软件的操作和使用,发觉该软件异常强大,而且有许多快捷键操作,在学期末时查阅了相关资料,特整理如下,供学习借鉴. 一.工具快捷键 二 ...
- Lucene系列一:搜索引擎核心理论
一.为什么需要搜索引擎 问题1:数据库索引的原理是怎样的? 索引原理:对列值创建排序存储,数据结构={列值.行地址}.在有序数据列表中就可以利用二分查找快速找到要查找的行的地址,再根据地址直接取行数据 ...
- Swing AWT一套新的图形界面系统
Swing 是在AWT的基础上构建的一套新的图形界面系统,它提供了AWT 所能够提供的所有功能,并且用纯粹的Java代码对AWT 的功能进行了大幅度的扩充. 例如说并不是所有的操作系统都提供了对树形控 ...
- C#数据结构----------------------------哈希表源码解析
转载: C# Hashtable源码剖析 源代码版本为 .NET Framework 4.6.1 本系列持续更新,敬请关注 有投入,有产出. Hashtable实现一个哈希表(也叫散列表),将键映射到 ...
- 九章算法:BAT国内班 - 课程大纲
第1章 国内笔试面试风格及准备方法 --- 分享面试经验,通过例题分析国内面试的风格及准备方法 · 1) C/C++部分: 实现 memcpy 函数 STL 中 vector 的实现原理 · 2)概率 ...
- Servlet下载文件迅雷不支持问题真相之一
问题描述 最近在做一个下载文件的Servlet,直接使用浏览器的下载功能,完美支持,结果测试人员使用迅雷下载,就不行了,下载也能成功完成,只是迅雷下载的文件大小是悲催的0KB 真相搜罗 网上有很多帖子 ...
- Linux账号和权限管理
一. 用户和组的管理 - Linux中用户种类 种类 特点 root 是管理员,拥有至高无上的权限,不受限制,UID为0 普通用户 管理员创建的用户,受权限限制,UID一般从500开始,可以登录系统 ...
- Windows下安装Oracle12C(二)
一.安装Oracle 参考 Windows下安装Oracle12C(一) 二.新建用户 1. 安装完成后,启动SQLPlus,然后输入内置的用户名和密码 用户名:sys 密码:as sysdba ...
- 1. 请问PHP里的ECHO是什么意思 ?请问PHP里的ECHO是什么意思???有什么作用???又应该怎么使用???
直接输出字符或字符串的意思: 例如:echo "abc"; 就会输出abc echo 'abc' 一样是输出abc . 如果仅仅只输出字符串的话,单引号和双引号是输出内容是一样的, ...