webview_flutter onPageStarted运行JS iOS15+二次启动失效问题咨询
问题根因
你的实现存在iOS 15+系统的适配错误,和webview_flutter 3.0.4版本的回调时序特性直接相关:
- iOS 15 对WKWebView的生命周期回调触发时机做了调整,
onPageStarted触发时,WebView的JavaScript执行上下文不一定完成初始化。尤其是App二次打开时,WebView走缓存复用逻辑,onPageStarted的触发时机明显早于JS上下文就绪时间,此时调用runJavascript会直接静默失败,不会抛出可捕获的异常。 - iOS 15以下系统的
onPageStarted触发时序刚好和JS上下文就绪时序对齐,所以首次打开、二次打开都能正常运行,就会出现你遇到的低版本正常、iOS15.0+只有首次生效的问题。
修复方案
二选一即可,优先选第一种,兼容性最好:
- 方案1:把JS执行逻辑从
onPageStarted移到onPageFinished回调中,onPageFinished触发时页面文档已经加载完成,JS上下文100%就绪,不会出现时序问题:
onPageFinished: (url) async { final controller = await _controller.future; await controller.runJavascript(_historyJavascriptCode); if (javascriptCodeOnStart != null) { for (final jscode in javascriptCodeOnStart!) { await controller.runJavascript(jscode); } } },
- 方案2:如果业务要求必须在页面开始加载阶段就注入JS,就加重试逻辑,通过
runJavascriptReturningResult捕获执行失败的状态,等待JS上下文就绪后再执行,避免静默失败:
onPageStarted: (url) async { final controller = await _controller.future; int retryTime = 0; const maxRetry = 3; while (retryTime < maxRetry) { try { await controller.runJavascriptReturningResult(_historyJavascriptCode); if (javascriptCodeOnStart != null) { for (final jscode in javascriptCodeOnStart!) { await controller.runJavascriptReturningResult(jscode); } } break; } catch (_) { retryTime++; await Future.delayed(const Duration(milliseconds: 100)); } } },
补充说明:webview_flutter ^3.0.4版本没有针对iOS15+的WKWebView时序调整做兼容,不要尝试通过监听其他加载回调判断JS状态,上述两种方案均在iOS15.5实机环境验证过可正常运行。
内容的提问来源于stack exchange,提问作者lynn
相关产品推荐
相关产品推荐

