在canInitWithRequest的YES响应之后,NSURLProtocol不会被要求加载
我正在注册一个NSURLProtocol的实现来做一些自定义处理某些URL请求(我通过设置它们的属性来标记这些请求)。 这些URL请求来自UIWebView的加载方法。
- 创buildUI Web视图(启动后第一次加载)
- 加载内容
- 破坏networking视图
- 创build一个新的Web视图(后续加载)
- 加载内容
我看到步骤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。
- 为原始请求的查询参数添加一个唯一的参数。 我select了'key = 000000'这个值是零引导的六位数的随机数。
- 在协议中,
initWithRequest:cachedResponse:client
canonicalRequestForRequest:
的keycanonicalRequestForRequest:
和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];