1

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

  1. 创建 UI Web 视图(启动后首次加载)
  2. 加载内容
  3. 销毁网页视图
  4. 创建一个新的 Web 视图(后续加载)
  5. 加载内容

我看到第 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 本身的实现。如果我真的希望我的协议成为负责加载的实体,关于如何解决这个问题的任何想法?

4

2 回答 2

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];
于 2016-12-27T08:44:50.047 回答
0

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

  1. 将唯一参数添加到原始请求的查询参数。我选择了“key=000000”,其中的值是零引导的六位随机数。
  2. 在协议中,将 key incanonicalRequestForRequest:和 in剥离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;
}

我的初始化代码如下所示:

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

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

于 2014-10-16T15:36:17.597 回答