在canInitWithRequest的YES响应之后,NSURLProtocol不会被要求加载

我正在注册一个NSURLProtocol的实现来做一些自定义处理某些URL请求(我通过设置它们的属性来标记这些请求)。 这些URL请求来自UIWebView的加载方法。

  1. 创buildUI Web视图(启动后第一次加载)
  2. 加载内容
  3. 破坏networking视图
  4. 创build一个新的Web视图(后续加载)
  5. 加载内容

我看到步骤2和步骤5之间的显着不同的行为。我的NSURLProtocol实现pipe理caching的数据,并被devise来处理请求。 如果我在请求中没有检测到我的属性,我会再次检查特定的URL(用于debugging)。 在任何情况下, canInitWithRequest将返回YES

启动后首次加载:

 2014-10-15 11:37:11.403 MYApp[5813:60b] MYURLProtocol canInitWithRequest: Matched property in request: <0x15ebbb40> https://example.com/ 2014-10-15 11:37:11.404 MYApp[5813:60b] MYURLProtocol canInitWithRequest: Matched property in request: <0x15dc8da0> https://example.com/ 2014-10-15 11:37:11.409 MYApp[5813:60b] MYURLProtocol canInitWithRequest: Matched property in request: <0x15ee5ef0> https://example.com/ 2014-10-15 11:37:11.409 MYApp[5813:60b] MYURLProtocol canInitWithRequest: Matched property in request: <0x15ee6240> https://example.com/ 2014-10-15 11:37:11.410 MYApp[5813:60b] MYURLProtocol initWithRequest:cachedResponse:client: Request: https://example.com/ 2014-10-15 11:37:11.411 MYApp[5813:60b] MYURLProtocol canInitWithRequest: Matched property in request: <0x15ee69d0> https://example.com/ 2014-10-15 11:37:11.415 MYApp[5813:9c07] MYURLProtocol startLoading Loading <0x15ee6240> https://example.com/ ... A bunch of loading of assets occurs (cached responses) ... 2014-10-15 11:37:12.497 MYApp[5813:60b] MyWebViewController webViewDidFinishLoad: Finished loading 

其他人指出,对协议有多个相同资产的调用,这不是一个问题,但有趣的是每次调用一个新的对象,它是第四个(4)对象传递给startLoading 。 不过,这里没有真正的问题。

后续加载:

 2014-10-15 11:11:27.466 MYApp[5782:60b] MYURLProtocol canInitWithRequest: Matched property in request: <0x1727c310> https://example.com/ 2014-10-15 11:11:27.467 MYApp[5782:60b] MYURLProtocol canInitWithRequest: Matched property in request: <0x145b1d90> https://example.com/ 2014-10-15 11:11:27.488 MYApp[5782:560f] MYURLProtocol canInitWithRequest: Matched URL in request: <0x17266060> https://example.com/ 2014-10-15 11:11:27.669 MYApp[5782:60b] MYWebViewController webViewDidFinishLoad: Finished loading 

在我看来,这是行为出乎意料的地方。 看起来,属性已经被第三次传递给canInitWithRequest时被剥离了请求,然后,即使我们回答YES我们也从未真正得到了入口 – 页面完全返回到UIWebView ,没有随后的资产要求。 这是请求看起来像什么时候创build的:

 NSURLRequest *request = [NSURLRequest requestWithURL:myURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; [self.webView loadRequest:request]; 

为什么当我说我的协议可以处理这个请求时,是不是有机会这样做? 我的猜测是答案是在UIWebView本身的实现。 任何关于如何解决这个问题的想法,如果我真的希望我的协议是加载负责任的实体?

我能够通过caching破坏UIWebViewcaching来解决这个问题,而不是破坏NSURLCache。

  1. 为原始请求的查询参数添加一个唯一的参数。 我select了'key = 000000'这个值是零引导的六位数的随机数。
  2. 在协议中, initWithRequest:cachedResponse:client canonicalRequestForRequest:的key canonicalRequestForRequest:initWithRequest:cachedResponse:client

我的剥离代码看起来像这样(可能有一个更清晰的方式来剥离参数,但这个工程):

 + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { NSURLRequest *canonicalRequest = request; BOOL myProtocolRequest = [[NSURLProtocol propertyForKey:kMYProtocolRequest inRequest:request] boolValue]; if (myProtocolRequest) { NSMutableURLRequest *mutableRequest = [request mutableCopyWorkaround]; NSString *originalURLString = mutableRequest.URL.absoluteString; NSString *regexString = [NSString stringWithFormat:@"(?:[?&])(key=[[:digit:]]{%d}&*)", kMYKeyLength]; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexString options:0 error:0]; NSTextCheckingResult *result = [regex firstMatchInString:originalURLString options:0 range:NSMakeRange(0, originalURLString.length)]; if (result.numberOfRanges > 1) { NSRange keyRange = [result rangeAtIndex:1]; NSLog(@"Removing '%@' from request", [originalURLString substringWithRange:keyRange]); NSString *replacementURLString = [originalURLString stringByReplacingCharactersInRange:keyRange withString:@""]; mutableRequest.URL = [NSURL URLWithString:replacementURLString]; canonicalRequest = mutableRequest; } } return canonicalRequest; } 

我的init代码如下所示:

 - (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client { self = [super initWithRequest:[MYURLProtocol canonicalRequestForRequest:request] cachedResponse:cachedResponse client:client]; return self; } 

我不喜欢我必须这样做,但我终于得到了我想要的行为。 希望它可以帮助那里的人。

 *** Way to clear the cache of webview ********** Follow this code: NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage]; for (NSHTTPCookie *cookie in [storage cookies]) { [storage deleteCookie:cookie]; } [[NSUserDefaults standardUserDefaults] synchronize];