注册多个 NSURLProtocol 子类 & 如何拦截 WKWebView

时间:2021-08-19
本文章向大家介绍注册多个 NSURLProtocol 子类 & 如何拦截 WKWebView,主要包括注册多个 NSURLProtocol 子类 & 如何拦截 WKWebView使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

注册多个 NSURLProtocol 子类

当有多个自定义 NSURLProtocol 子类注册到系统中的话,会按照他们注册的反向顺序依次调用 URL 加载流程,也就是最后注册的 NSURLProtocol 会被优先判断。

对于通过配置 NSURLSessionConfiguration 对象的 protocolClasses 属性来注册的情况,protocolClasses 数组中只有第一个 NSURLProtocol 会起作用,后续的 NSURLProtocol 就无法拦截到了。

所以 OHHTTPStubs 在注册 NSURLProtocol 子类的时候是这样处理的:

+ (void)setEnabled:(BOOL)enable forSessionConfiguration:(NSURLSessionConfiguration*)sessionConfig
{
    // Runtime check to make sure the API is available on this version
    if ([sessionConfig respondsToSelector:@selector(protocolClasses)]
        && [sessionConfig respondsToSelector:@selector(setProtocolClasses:)])
    {
        NSMutableArray * urlProtocolClasses = [NSMutableArray arrayWithArray:sessionConfig.protocolClasses];
        Class protoCls = HTTPStubsProtocol.class;
        if (enable && ![urlProtocolClasses containsObject:protoCls])
        {
            // 将自己的 NSURLProtocol 插入到 protocolClasses 的第一个,进行拦截
            [urlProtocolClasses insertObject:protoCls atIndex:0];
        }
        else if (!enable && [urlProtocolClasses containsObject:protoCls])
        {
            // 拦截完成后移除
            [urlProtocolClasses removeObject:protoCls];
        }
        sessionConfig.protocolClasses = urlProtocolClasses;
    }
    else
    {
        NSLog(@"[OHHTTPStubs] %@ is only available when running on iOS7+/OSX9+. "
              @"Use conditions like 'if ([NSURLSessionConfiguration class])' to only call "
              @"this method if the user is running iOS7+/OSX9+.", NSStringFromSelector(_cmd));
    }
}
复制代码

如何拦截 WKWebView

虽然 NSURLProtocol 无法直接拦截 WKWebView,但其实还是有解决方案的。就是使用 WKBrowsingContextController 和 registerSchemeForCustomProtocol

// 注册 scheme
Class cls = NSClassFromString(@"WKBrowsingContextController");
SEL sel = NSSelectorFromString(@"registerSchemeForCustomProtocol:");
if ([cls respondsToSelector:sel]) {
    // 通过 http 和 https 的请求,同理可通过其他的 Scheme 但是要满足 URL Loading System
    [cls performSelector:sel withObject:@"http"];
    [cls performSelector:sel withObject:@"https"];
}
复制代码

但由于这涉及到了私有方法,直接引用无法过苹果的机审,所以使用的时候需要对字符串做下处理,比如对方法名进行算法加密处理等,实测也是可以通过审核的。

总之,NSURLProtocol 非常强大,无论是优化 App 的性能,还是拓展功能,都具有很强的可塑空间,但在使用的同时,又要多关注它带来的问题。尽管它在很多框架或者知名项目中都已经得以应用,其奥义依然值得开发者们去深入研究。


作者:FiTeen
链接:https://juejin.cn/post/6844904079458566152
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
------------------越是喧嚣的世界,越需要宁静的思考------------------ 合抱之木,生于毫末;九层之台,起于垒土;千里之行,始于足下。 积土成山,风雨兴焉;积水成渊,蛟龙生焉;积善成德,而神明自得,圣心备焉。故不积跬步,无以至千里;不积小流,无以成江海。骐骥一跃,不能十步;驽马十驾,功在不舍。锲而舍之,朽木不折;锲而不舍,金石可镂。蚓无爪牙之利,筋骨之强,上食埃土,下饮黄泉,用心一也。蟹六跪而二螯,非蛇鳝之穴无可寄托者,用心躁也。

原文地址:https://www.cnblogs.com/feng9exe/p/15163529.html