<commit_before>---
layout: post
title: UIWebView URL拦截
date: 2015-06-19
comments: true
archive: false
---
拦截URL实现UIWebView加载本地资源. 

iCab Mobile(一款iOS平台的网页浏览器)要实现一个拦截管理器来过滤页面上的广告及其他东西。 它有一个简单的基于URL过滤规则的列表（通常由用户维护），当页面包含的资源（图片，js，css等）文件的URL存在于规则列表中时，资源就不会被加载。

但看一下UIWebView类的API，会发现我们没有办法知道UIWebView正在加载什么资源，更糟的是，当你希望过滤掉某些资源文件的时候，没有方法可以强制UIWebView不去加载这些文件，

拦截器看起来貌似没有可能实现。

当然还是有解决方案的，否则这篇文件就没什么卵用。

正如上面所说，实现拦截器不能靠UIWebView，因为UIWebView没有提供任何有用的API。

对UIWebView的所有请求，要找到一个能中断所有HTTP 请求的切入点，我们需要先了解一下Cocoa的[URL Loading System](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html)，因为UIWebView是使用[URL Loading System](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html)从web端取数据的。我们需要的切入点NSURLCache类就是[URL Loading System](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html)的一部分。虽然目前iOS系统不会在磁盘上缓存任何数据（后面的iOS系统版本或许会有不同），因此在UIWebView开始加载前，NSURLCache管理的缓存数据通常为空，但UIWebView仍然会检测所请求资源文件是否存在于缓存。所以我们需要做的只是继承NSURLCache并重载其方法：

	- (NSCachedURLResponse*)cachedResponseForRequest:(NSURLRequest*)request

UIWebView请求所有资源时都会调用这个方法。因为我们只需要在这个方法里判断请求的URL是否是我们想拦截的。如果是则创建一个没有内容的假response，否则只需调用super方法即可。

如下是实现细节：

1.继承NSURLCache:

头文件FilteredWebCache.h:

    @interface FilteredWebCache : NSURLCache
    {<commit_msg>add files<commit_after>---
layout: post
title: UIWebView URL拦截
date: 2015-06-19
comments: true
archive: false
---
拦截URL实现UIWebView加载本地资源. 


iCab Mobile(一款iOS平台的网页浏览器)要实现一个拦截管理器来过滤页面上的广告及其他东西。 它有一个简单的基于URL过滤规则的列表（通常由用户维护），当页面包含的资源（图片，js，css等）文件的URL存在于规则列表中时，资源就不会被加载。

但看一下UIWebView类的API，会发现我们没有办法知道UIWebView正在加载什么资源，更糟的是，当你希望过滤掉某些资源文件的时候，没有方法可以强制UIWebView不去加载这些文件，

拦截器看起来貌似没有可能实现。

当然还是有解决方案的，否则这篇文件就没什么卵用。

正如上面所说，实现拦截器不能靠UIWebView，因为UIWebView没有提供任何有用的API。

对UIWebView的所有请求，要找到一个能中断所有HTTP 请求的切入点，我们需要先了解一下Cocoa的[URL Loading System](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html)，因为UIWebView是使用[URL Loading System](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html)从web端取数据的。我们需要的切入点NSURLCache类就是[URL Loading System](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html)的一部分。虽然目前iOS系统不会在磁盘上缓存任何数据（后面的iOS系统版本或许会有不同），因此在UIWebView开始加载前，NSURLCache管理的缓存数据通常为空，但UIWebView仍然会检测所请求资源文件是否存在于缓存。所以我们需要做的只是继承NSURLCache并重载其方法：

	- (NSCachedURLResponse*)cachedResponseForRequest:(NSURLRequest*)request

UIWebView请求所有资源时都会调用这个方法。因为我们只需要在这个方法里判断请求的URL是否是我们想拦截的。如果是则创建一个没有内容的假response，否则只需调用super方法即可。

如下是实现细节：

1.继承NSURLCache:

头文件FilteredWebCache.h:

    @interface FilteredWebCache : NSURLCache
    {
{'fraction_non_alphanumeric': 0.08961748633879782, 'fraction_numerical': 0.006557377049180328, 'mean_word_length': 11.425339366515837, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 6, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7478503', 'n_tokens_mistral': 1599, 'n_tokens_neox': 1751, 'n_words': 73}