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

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

  • 创建UI Web视图(启动后第一次加载)
  • 加载内容
  • 破坏网络视图
  • 创建一个新的Web视图(后续加载)
  • 加载内容
  • 我在步骤2和步骤5之间看到了显着不同的行为。我的NSURLProtocol实现管理缓存数据,并且旨在处理这些请求。 如果我在请求中没有检测到我的属性,我会再次检查特定的URL(用于调试)。 无论哪种情况, 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个(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传递给canInitWithRequest ,属性已经被剥离,然后,即使我们回应YES我们也从未真正得到了入口 - 页面完全返回到UIWebView ,没有随后的资产请求。 这是请求在创建时的样子:

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

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


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

  • 为原始请求的查询参数添加一个唯一的参数。 我选择了'key = 000000',其值为零导致六位数的随机数。
  • 在协议中,删除canonicalRequestForRequest:的密钥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];
    
    链接地址: http://www.djcxy.com/p/34843.html

    上一篇: NSURLProtocol isn't asked to load after YES response to canInitWithRequest

    下一篇: Loading resources from relative paths through NSURLProtocol subclass