NSURLProtocol
Overview
NSURLProtocol对象处理特定协议的URL数据加载。 NSURLProtocol类本身是一个抽象类,它提供用于处理具有特定scheme的URL的基础结构。 你可以通过创建NSURLProtocol的子类为应用支持的任何自定义协议或URL schemes。
应用不需要直接实例化一个NSURLProtocol子类。 当下载开始时,系统创建适当的协议对象来处理相应的URL请求。 所有你需要做的是定义您的协议类,并在应用程序启动时调用registerClass:
类方法,以便系统知道你的协议。
注意:不能在watchOS 2或更高版本中使用此类自定义URL schemes和协议。
为了支持协议特定请求的定制,Apple鼓励我们为NSURLRequest和NSMutableURLRequest添加类别来满足我们的需求。 以这种方式扩展NSURLRequest和NSMutableURLRequest功能可以在调用NSURLProtocol的类方法propertyForKey:inRequest:
和setProperty:forKey:inRequest :
来存储和检索特定于协议的数据请求.
协议实现者的重要职责是为其成功处理的每个请求创建一个NSURLResponse。 协议实现者可能希望创建一个定制的,可变的NSURLResponse类来提供特定于协议的信息。
Symbols
Creating Protocol Objects
-
- (instancetype)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client
初始化并返回这个类;
request:NSURLProtocol对象的URL请求。 此request:NSURLProtocol被retain。
cachedResponse:请求响应的缓存; 如果请求没有现有的缓存,则可能为nil。
client:调用者用来与URL加载系统通信实现了的NSURLProtocolClient协议的对象。 此client被retain。子类应该覆盖此方法以执行任何自定义初始化操作。 应用程序永远不应该显式调用此方法。
这是NSURLProtocol的指定的初始化方法。
Registering and Unregistering Protocol Classes
-
+ (BOOL)registerClass:(Class)protocolClass
尝试注册NSURLProtocol的子类,使其对URL加载系统可见。唯一的失败情况是如果protocolClass不是NSURLProtocol的子类。
当URL加载系统开始加载请求时,依次查询每个注册的协议类,以查看是否可以使用指定的请求进行初始化。 当第一个NSURLProtocol子类的
canInitWithRequest:
方法返回YES时,这个子类将用于执行URL加载。不能保证所有注册的协议类都被查询。
所有的子类按照注册的相反顺序进行查询。
-
+ (void)unregisterClass:(Class)protocolClass
注销NSURLProtocol的指定子类。
调用此方法后,URL加载系统不再查询protocolClass。
Determining If a Subclass Can Handle a Request
+ (BOOL)canInitWithRequest:(NSURLRequest *)request
返回NSURLProtocol的子类是否可以处理指定的请求。
子类应检查请求,并确定此方法是否可以执行该请求的加载。
这是一个抽象的方法,子类必须实现此方法。
Getting and Setting Request Properties
-
+ (id)propertyForKey:(NSString *)key inRequest:(NSURLRequest *)request
返回与指定的请求中指定的关键字关联的属性。如果没有该key,返回nil;
该方法为协议实现者提供了访问与NSURLRequest对象相关的特定于协议的信息的接口。
-
+ (void)setProperty:(id)value forKey:(NSString *)key inRequest:(NSMutableURLRequest *)request
给指定的请求设置与指定键相关联的属性。
该方法用于为协议实现者提供一个用于定制与NSMutableURLRequest对象相关联的协议特定信息的接口。
看了下大家的demo,这两个方法基本上都是用来标记指定请求的;
-
+ (void)removePropertyForKey:(NSString *)key inRequest:(NSMutableURLRequest *)request
移除给指定的请求的指定key相关联的属性。
Providing a Canonical Version of a Request
-
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request
返回指定请求的规范版本。即返回通过request来自定义的请求
每个具体的协议实现都是由“规范”所指定的。 协议应该保证相同的输入请求总是产生相同的规范形式。
在实现此方法时应特别注意,因为请求的规范形式用于查找URL缓存中的对象,这是在NSURLRequest对象之间执行相等检查的进程。
这是一个抽象的方法,子类必须提供一个实现。
一般情况下我们会直接返回request或者是修改请求头部信息后再返回;
Determining If Requests Are Cache Equivalent
-
+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b
返回两个请求在做缓存的时候是否相同;
如果aRequest和bRequest在缓存的时候相同,则为YES,否则为NO。 当且仅当这些请求将被相同的协议处理并且该协议在执行特定于检查之后它们仍是等效的,才认为他们相等。该方法的实现用来确定请求是否应被视为等效的。 子类可以覆盖此方法以提供协议特定的比较。
Starting and Stopping Downloads
-
- (void)startLoading
开始加载通过协议定制了的请求;
当调用此方法时,子类实现应开始加载请求,并通过NSURLProtocolClient协议向URL加载系统提供反馈。子类必须实现此方法。
-
- (void)stopLoading
停止加载通过协议定制了的请求;
当调用此方法时,子类实现应该停止加载请求。 这可能是响应于取消操作,因此协议实现必须能够在加载进行时处理此调用。 当协议接收到此方法的调用时,它也应该停止向客户端发送通知。子类必须实现此方法。
Getting Protocol Attributes
-
@property(readonly, copy) NSCachedURLResponse *cachedResponse
调用者缓存的响应数据;
如果不在子类中覆盖,则此方法返回在初始化时存储的缓存响应。
-
@property(readonly, retain) id<NSURLProtocolClient> client
调用者用来与URL加载系统通信的对象。
-
@property(readonly, copy) NSURLRequest *request
调用者的请求;
Initializers
-
- (instancetype)initWithTask:(NSURLSessionTask *)task cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client
这个方法是在其NSURLSessionTaskAdditions分类中定义的方法;文档和头文件中并没有介绍;与该方法类似的还有
+ (BOOL)canInitWithTask:(NSURLSessionTask *)task
方法和@property(readonly, copy) NSURLSessionTask *task
方法;
这里我就不妄自猜测这些方法的作用,应该主要用在与session相关的操作上的,如果以后碰到了用法再回来添加进来;
NSURLProtocolClient
上文中出现了这个协议,我们接下来看下这个协议到底定义了一些什么方法吧,虽然我们并不需要去是实现这些功能。
NSURLProtocolClient协议提供NSURLProtocol子类与URL加载系统进行通信的接口。 应用程序永远不需要实现此协议。
-
- (void)URLProtocol:(NSURLProtocol *)protocol cachedResponseIsValid:(NSCachedURLResponse *)cachedResponse
向URL加载系统发送缓存响应有效的消息。
-
- (void)URLProtocol:(NSURLProtocol *)protocol didCancelAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
向URL加载系统发送身份认证已被取消的消息。
-
- (void)URLProtocol:(NSURLProtocol *)protocol didFailWithError:(NSError *)error
发送加载任务因为error而失败;
-
- (void)URLProtocol:(NSURLProtocol *)protocol didLoadData:(NSData *)data
NSURLProtocol子类实例协议在加载数据时将此消息发送到 NSURLProtocolClient 。
-
- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
向URL加载系统发送指示已接收到身份验证。
-
- (void)URLProtocol:(NSURLProtocol *)protocol didReceiveResponse:(NSURLResponse *)response cacheStoragePolicy:(NSURLCacheStoragePolicy)policy
向URL加载系统发送协议实现已经为请求创建了响应对象的消息。
实现中应该使用提供的缓存策略来确定是否将响应存储在高速缓存中。
-
- (void)URLProtocol:(NSURLProtocol *)protocol wasRedirectedToRequest:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
向URL加载系统发送协议实现已被重定向的消息。
-
- (void)URLProtocolDidFinishLoading:(NSURLProtocol *)protocol
向URL加载系统发送协议实现已经完成加载的消息。
参考
iOS开发之--- NSURLProtocol
iOS监控-DNS劫持
让 WKWebView 支持 NSURLProtocol
iOS 开发中使用 NSURLProtocol 拦截 HTTP 请求
iOS中UIWebView与WKWebView、JavaScript与OC交互、Cookie管理看我就够(中)
网友评论