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

时间:2014-10-15 18:56:50

标签: ios cocoa-touch uiwebview nsurl nsurlprotocol

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

  1. 创建UI网页视图(启动后首次加载)
  2. 加载内容
  3. 销毁网络视图
  4. 创建新的Web视图(后续加载)
  5. 加载内容
  6. 我发现第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时,属性已从请求中删除,然后,即使我们回复YES,我们也从未真正进入过 - 该页面只是返回到完整的UIWebView,没有后续的资产请求。以下是创建请求时的样子:

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

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

2 个答案:

答案 0 :(得分:1)

*** 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];

答案 1 :(得分:0)

我能够通过缓存清除UIWebView缓存来解决此问题,同时不破坏NSURLCache。

  1. 在原始请求的查询参数中添加一个唯一的参数。我选择'key = 000000',其中值为零导数的六位数随机数。
  2. 在协议中,删除canonicalRequestForRequest:initWithRequest:cachedResponse:client
  3. 中的密钥

    我的剥离代码看起来像这样(可能有一种更简洁的方法来剥离参数,但这有效):

    + (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;
    }
    

    我的初始化代码如下:

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

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