美文网首页iOS开发踩坑
WKWebView的网络拦截问题

WKWebView的网络拦截问题

作者: mrChan1234 | 来源:发表于2018-05-10 10:13 被阅读0次

    利用NSURLProtocol拦截WKWebView的请求
    我们知道 ,ios 8.0以后,apple给出了一个WKWebView来替换 UIWebView,前者比后者在加载速度方面优化了很多,但是也有不少坑点,比如在拦截wkwebView的请求上,apple始终没有给出明确的API供开发者使用,正常情况下,我们自定义一个NSURLProtocol类,然后在AppDelegate里面register一波,就可以拦截到app内部所有的网络请求,但是你会发现,wkwebView并不吃这一套,what the fuck!,这一点在网上有人说wkwebView的请求是在单独的进程里面,为了性能方面的考虑,所以不走NSURLProtocol,但是通过打断点会发现,它会走一下+ (BOOL)canInitWithRequest:(NSURLRequest *)request,然而这就尴尬了,为啥他会走一下,然后就一直不走了呢?于是我开始去研究了一波技术讨论,请教了一些大牛,找到了解决方案:写一个单独的NSURLProtocol类的分类方法,这里要提醒一下:由于这是私有方法,可能导致上线被拒!!!
    .h文件:

    + (void)wk_registerScheme:(NSString*)scheme;
    
    + (void)wk_unregisterScheme:(NSString*)scheme;
    

    .m文件:

    FOUNDATION_STATIC_INLINE Class ContextControllerClass() {
        static Class cls;
        if (!cls) {
            cls = [[[WKWebView new] valueForKey:@"browsingContextController"] class];
        }
        return cls;
    }
    
    FOUNDATION_STATIC_INLINE SEL RegisterSchemeSelector() {
        return NSSelectorFromString(@"registerSchemeForCustomProtocol:");
    }
    
    FOUNDATION_STATIC_INLINE SEL UnregisterSchemeSelector() {
        return NSSelectorFromString(@"unregisterSchemeForCustomProtocol:");
    }
    
    @implementation NSURLProtocol (WebKitSupport)
    
    + (void)wk_registerScheme:(NSString *)scheme {
        Class cls = ContextControllerClass();
        SEL sel = RegisterSchemeSelector();
        if ([(id)cls respondsToSelector:sel]) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [(id)cls performSelector:sel withObject:scheme];
    #pragma clang diagnostic pop
        }
    }
    
    + (void)wk_unregisterScheme:(NSString *)scheme {
        Class cls = ContextControllerClass();
        SEL sel = UnregisterSchemeSelector();
        if ([(id)cls respondsToSelector:sel]) {
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Warc-performSelector-leaks"
            [(id)cls performSelector:sel withObject:scheme];
    #pragma clang diagnostic pop
        }
    }
    

    然后在AppDelegate里面去注册一波scheme,一般是注册http和https,然后打一波断点你就会发现,可以拦截了,可以为所欲为了,一般对wkwebView的拦截的原因一般是要加一些特定的请求头或者拦截广告(接触的项目里面是这样干的)
    + (BOOL)canInitWithRequest:(NSURLRequest *)request在这里进行过滤判断,
    + (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request这里面可以拿到被拦截的请求,可以在这里面对这个request进行二次处理,然后在startLoading方法里面自己进行自定义的处理!

    相关文章

      网友评论

        本文标题:WKWebView的网络拦截问题

        本文链接:https://www.haomeiwen.com/subject/ulcslftx.html