iOS Flutter WebView注入JS触发FWFEvaluateJavaScriptError异常求助
问题排查与解决方案
1. 解决重复注入JS引发的冲突
你的代码在onPageFinished中每次页面加载完成都注入监听JS,会导致多次覆盖history.pushState、重复绑定popstate事件,引发JS上下文冲突,触发执行错误。
给JS添加执行标记,避免重复注入:
final pushStateSpyJavaScript = ''' if (!window.__pushStateSpyInjected) { window.__pushStateSpyInjected = true; ((history)=>{ const org=history.pushState; history.pushState=(state,_,url)=>{ org.apply(history, [state,_,url]); if(url) { window.flutter.postMessage(url.toString()); } }; addEventListener('popstate', (event) => window.flutter.postMessage(location.href.toString())); })(window.history); } ''';
2. 处理window.flutter未就绪的情况
页面刚加载完成时,Flutter的JavaScriptChannel可能还未初始化,直接调用window.flutter.postMessage会触发JS报错,进而抛出PlatformException。
给postMessage添加安全判断:
final pushStateSpyJavaScript = ''' if (!window.__pushStateSpyInjected) { window.__pushStateSpyInjected = true; ((history)=>{ const org=history.pushState; history.pushState=(state,_,url)=>{ org.apply(history, [state,_,url]); if(url && window.flutter?.postMessage) { window.flutter.postMessage(url.toString()); } }; addEventListener('popstate', (event) => { if (window.flutter?.postMessage) { window.flutter.postMessage(location.href.toString()); } }); })(window.history); } ''';
也可以延迟注入JS,给Channel初始化留时间:
onPageFinished: (url) { onUrlChanged(url); Future.delayed(const Duration(milliseconds: 300), () { webViewController.runJavaScript(pushStateSpyJavaScript); }); },
3. 获取JS执行的具体错误信息
用runJavaScriptReturningResult替代runJavaScript,能捕获更详细的JS错误,帮助定位问题:
onPageFinished: (url) { onUrlChanged(url); webViewController.runJavaScriptReturningResult(pushStateSpyJavaScript) .catchError((error) { print('JS执行错误详情: $error'); }); },
4. 确认WebView开启JS支持
检查WebView配置是否开启了JavaScript,否则注入的JS无法执行:
final webViewController = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) // 必须开启 ..addJavaScriptChannel('flutter', onMessageReceived: (message) { onUrlChanged(message.message); });
5. 限制JS仅在主窗口执行
如果页面包含iframe,注入的JS会在iframe中执行,但iframe中不存在window.flutter,会引发错误。添加主窗口判断:
final pushStateSpyJavaScript = ''' if (window.top === window && !window.__pushStateSpyInjected) { window.__pushStateSpyInjected = true; // 原有监听代码 } ''';
内容的提问来源于stack exchange,提问作者rekire
相关产品推荐
相关产品推荐

