iOS中的中间人-NSURLProtocol 的原理和使用实例

Part 1: 使用范围

  • 能拦截NSURLRequest请求

When an
NSURLSession, NSURLConnection, or NSURLDownload object initiates a connection for an NSURLRequest
object, the URL loading system consults each of the registered NSURLProtocol classes in the reverse order of their registration

  • 通过CFNetwork层CFHTTPMessageCreateRequest是无法拦截的

Part 2: 作用机制

The URL loading system is responsible for creating and releasing NSURLProtocol instances when connections start and complete. Your app should never create an instance of NSURLProtocol directly.
When an NSURLProtocol subclass is initialized by the URL loading system, it is provided a client object that conforms to the NSURLProtocolClient protocol. The NSURLProtocol subclass sends messages from the NSURLProtocolClient protocol to the client object to inform the URL loading system of its actions as it
creates a response, receives data, redirects to a new URL, requires authentication, and completes the load.
If the custom protocol supports authentication, then it must conform to the
NSURLAuthenticationChallengeSender protocol.

Part 3: 使用姿势

URL Loading system会在合适的时机,调用NSURLProtocol subclass中的以下方法:

  • -initWithRequest:cachedResponse:client:
  • -startLoading
    子类应该在此方法中,通过某种方式开始加载
  • -stopLoading
    子类应该在此方法中停止加载
  • -dealloc

子类在加载过程中,应该在合适的时机调用NSURLProtocolClient中的以下方法:

  • -URLProtocol:didReceiveResponse:cacheStoragePolicy: //收到了响应头时调用
  • -URLProtocol:didLoadData: //收到了响应数据时调用
  • -URLProtocolDidFinishLoading:或者 -URLProtocol: didFailWithError: //加载完成或者失败时调用

如果加载过程中有跳转,则应该直接调用以下方法:

  • -URLProtocol: wasRedirectedToRequest: redirectResponse:

2015.10.26更新:跟同事讨论时谈到了既然子类已经控制了加载的过程,为什么还要调用client的一些里的方法?结论是需要通知到URL loading system,上层的一系列关于网络请求状态的delegate方法(比如UIWebview)才能被调用。

Part 4: 实例

我写的两个NSURLProtocol子类,分别用NSURLConnection和ASI实现的,放在了github上:https://github.com/grittymindy/NSURLProtocolDemo

原文地址:https://www.cnblogs.com/mindyme/p/4898224.html