WKURLSchemeHandler接管h5 那些你不知道的坑

如果想知道h5缓存方案可以看我上一篇文章 juejin.cn/post/729966...

目前使用WKURLSchemeHandler接管H5已经成为主流方式,然而这种高度灵活的方案可能让你深陷一些令人沮丧的困境。在实践中,你将面临许多许多的问题。下面咱们来聊聊我踩的坑。

1、我们都了解通过WKURLSchemeHandler接管H5实现缓存的方式一定要实现webView:(nonnull WKWebView *)webView startURLSchemeTask:(nonnull id<WKURLSchemeTask>)urlSchemeTask函数拦截所有请求的方式,但是这种方式却无法灵活地指定拦截的请求类型,例如只拦截GET请求,这确实令人头痛。如果有其他小伙伴有更优雅的解决方案,非常欢迎留言分享。共同探讨如何更好地优化这个问题。

2、如果要拦截必然要通过WKURLSchemeTask协议的didReceiveResponse didReceiveData函数告诉webview,相信你肯定遇到过一个崩溃也就是task已经stop了,你依然调用WKURLSchemeTask协议函数。 于是我通过查找资料发现网友都说可以通过一个map来控制,也就是stop的url放入到一个map中然后再调用协议判断如果map中已经含有,就不再调用,如下代码

less 复制代码
if ([self.hashTable containsObject:urlSchemeTask.request.URL.absoluteString]) {
            return;
        }

        @try {
            if (error) {
                [urlSchemeTask didFailWithError:error];

            } else {

                [urlSchemeTask didReceiveResponse:response];

                [urlSchemeTask didReceiveData:responseObject];

                [urlSchemeTask didFinish];

            }

            [self removeTaskUrl:urlSchemeTask.request.URL.absoluteString];

        } @catch (NSException *exception) {

        } @finally {

        }

这个方法当然是个好方法,奈何我们这个拦截是复用的,webview退出时候没有清理map,导致两个webview用同一个资源url,在正常情况回调时候判断了map里含有了这个url,导致一直不给webview回调,webview一直无法加载,一直无法加载,再也不会加载, 这里有个坑点,只要有一个请求不给webview回调,webview就会一直等待,不再继续加载

3.我们经常遇到的跨域问题,也就是webview的dns和图片以及资源的dns发现不一样,不允许解析,我翻阅了无法资料网友都说做缓存response都是存了data然后自己创建一个也就是如下方式

arduino 复制代码
[[NSHTTPURLResponse alloc] initWithURL:@"" MIMEType:@"xxx" expectedContentLength:text.lenth textEncodingName:@"xxx"]

信誓旦旦用了这种方式,结果加载图片失败,遇到了跨域问题,抓包图片里已经允许了跨域,为什么还是遇到了跨域问题,当然是我们在执行didReceiveResponse告诉webview的时候,压根没有header啊,相当于header里压根没有告诉webview允许跨域啊,于是修改了缓存,给网络请求的整个response整个缓存下来包含header,这里我采用了YYCache代码如下:

ini 复制代码
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;


            NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];

            if ([responseDic isKindOfClass:[NSData class]]) {

                dic[@"responseData"] = responseDic;

            }

            dic[@"response"] = response;

            [self.diskCache setObject:dic forKey:[self cacheKeyWithUrl:response.URL] withBlock:^{

  


            }];

完美解决跨域问题

4、ios 12.5崩溃问题,有一些无用的我请求,拦截之后不想做网络请求直接使用了

objectivec 复制代码
[[NSHTTPURLResponse alloc] initWithURL:nil MIMEType:@"" expectedContentLength:text.length textEncodingName:@""]

初始化一个reseponse通过didreceiveresponse给webview,结果ios 12.5无法获取版本号崩溃,改成如下即可

ini 复制代码
NSHTTPURLResponse *newResponse = [[NSHTTPURLResponse alloc] initWithURL:urlSchemeTask.request.URL statusCode:200 HTTPVersion:@"HTTP/2.0" headerFields:@{}];

以下是我目前遇到的坑点,如果有错误地方欢迎大家共同讨论。

相关推荐
程序员鱼皮1 天前
刚刚,Claude Opus 4.6 和 GPT-5.3-Codex 同时炸场!AI 编程要变天了
计算机·ai·程序员·互联网·软件开发
Stephen_Young2 天前
32岁程序员猝死:让我想起了我曾经的加班经历,庆幸自己还活着
程序员·工控
良许Linux2 天前
51单片机都有哪些优缺点
单片机·程序员·嵌入式·编程
程序员鱼皮4 天前
前特斯拉 AI 总监:AI 编程最大的谎言,是 “提效”
前端·后端·ai·程序员·开发
阿里嘎多学长4 天前
2026-02-02 GitHub 热点项目精选
开发语言·程序员·github·代码托管
良许Linux5 天前
DSP的选型和应用
后端·stm32·单片机·程序员·嵌入式
淘源码d7 天前
【开源可商用】高并发智慧校园SaaS平台核心源码:Spring Boot 微服务 + 多终端协同
java·程序员·智慧校园·源码·二次开发·软件源码·电子班牌系统
程序员鱼皮8 天前
7个神级技巧,彻底去除网站的 AI 味儿!
计算机·ai·程序员·互联网·网站·编程经验
程序员鱼皮11 天前
Agent Skills 傻瓜式教程,26 年最火 AI 技术就这?
计算机·ai·程序员·agent·编程经验
黑客-雨13 天前
DeepSeek-V3.2深度拆解:开源模型逆袭,GPT-5迎来劲敌!
人工智能·程序员·大模型·知识图谱·agent·大模型教程·deepseek-v3.2