首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >没有要求NSURLProtocol在对canInitWithRequest的YES响应之后加载

没有要求NSURLProtocol在对canInitWithRequest的YES响应之后加载
EN

Stack Overflow用户
提问于 2014-10-15 18:56:49
回答 2查看 2.1K关注 0票数 1

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

  1. 创建UI web视图(启动后第一次加载)
  2. 负载量
  3. 破坏网页视图
  4. 创建一个新的web视图(后续加载)
  5. 负载量

我在步骤2和步骤5之间看到了明显不同的行为。我的NSURLProtocol实现管理缓存的数据,并设计用于处理请求。如果在请求中没有检测到我的属性,我会再次检查特定的URL (用于调试)。在这两种情况下,canInitWithRequest都将返回YES

启动后第一次加载:

代码语言:javascript
运行
复制
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

其他人已经指出,对于同一资产有多个对协议的调用,这不是一个问题,不过有趣的是,每次用一个新对象调用它,它是传递给startLoading的第四个对象。尽管如此,这里并没有真正的问题。

后续负载:

代码语言:javascript
运行
复制
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,没有后续的资产请求。以下是创建请求时的样子:

代码语言:javascript
运行
复制
NSURLRequest *request = [NSURLRequest requestWithURL:myURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
[self.webView loadRequest:request];

当我说我的协议可以处理请求时,为什么不给它这样做的机会呢?我猜答案是在UIWebView本身的实现中。如果我真的想让我的协议成为负责加载的实体,对如何解决这个问题有什么想法吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-16 15:36:17

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

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

我的剥离代码如下所示(可能有一种更干净的方法来去除param,但这是可行的):

代码语言:javascript
运行
复制
+ (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代码如下所示:

代码语言:javascript
运行
复制
- (id)initWithRequest:(NSURLRequest *)request cachedResponse:(NSCachedURLResponse *)cachedResponse client:(id<NSURLProtocolClient>)client
{
    self = [super initWithRequest:[MYURLProtocol canonicalRequestForRequest:request] cachedResponse:cachedResponse client:client];
    return self;
}

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

票数 0
EN

Stack Overflow用户

发布于 2016-12-27 08:44:50

代码语言:javascript
运行
复制
*** 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
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26390036

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档