WKWebView是iOS应用中常用的网页加载组件,广泛应用于混合开发、H5页面嵌入以及App内Web功能实现。在实际开发过程中,开发者经常会遇到JavaScript运行异常,其中比较典型的问题就是:
TypeError: undefined is not an object
该错误表示JavaScript尝试访问一个未定义对象的属性或方法。例如:
JavaScriptuser.name
如果user不存在,就会抛出:
TypeError: undefined is not an object (evaluating 'user.name')
在WKWebView环境中,这类问题不仅可能来自前端代码本身,还可能与iOS原生交互、加载时机、JS注入、缓存以及版本兼容性有关。下面详细分析常见原因和解决方案。
一、理解TypeError: undefined is not an object错误
JavaScript属于弱类型语言,在运行过程中不会提前检查对象是否存在。当代码访问不存在的变量或属性时,就可能出现类似错误:
JavaScriptvar data; console.log(data.title);
执行后会出现:
TypeError: undefined is not an object
常见触发场景包括:
-
对象未初始化;
-
异步数据还没有返回;
-
DOM元素尚未加载;
-
iOS与JavaScript通信对象不存在;
-
JS文件加载顺序错误;
-
WKWebView环境与浏览器环境存在差异。
在普通浏览器中运行正常,但放入WKWebView后出现异常,通常说明运行环境发生了变化。
二、检查JavaScript对象是否存在
最常见的解决方式是增加对象存在性判断。
错误写法:
JavaScriptvar result = response.data.name;
如果response或者data不存在,就会导致异常。
推荐修改为:
JavaScriptif (response && response.data) { var result = response.data.name; }
或者使用ES6可选链:
JavaScriptvar result = response?.data?.name;
可选链能够避免因为空对象导致程序直接崩溃。
不过需要注意,部分旧版本iOS中的JavaScriptCore环境可能不支持最新语法,需要根据最低支持版本决定是否使用。
三、WKWebView中JS调用原生方法失败
WKWebView最容易出现该错误的地方,就是JavaScript调用iOS原生注入对象。
例如:
JavaScriptwindow.webkit.messageHandlers.nativeBridge.postMessage({ action:"login" });
如果没有正确注册nativeBridge,会出现:
TypeError: undefined is not an object
原因是:
JavaScriptwindow.webkit.messageHandlers.nativeBridge
实际不存在。
iOS端正确注册方式
Swift示例:
Swiftlet configuration = WKWebViewConfiguration() let controller = WKUserContentController() controller.add(self, name: "nativeBridge") configuration.userContentController = controller let webView = WKWebView( frame: .zero, configuration: configuration )
同时需要实现:
Swiftextension ViewController: WKScriptMessageHandler { func userContentController( _ userContentController: WKUserContentController, didReceive message: WKScriptMessage ) { if message.name == "nativeBridge" { print(message.body) } } }
JavaScript调用前可以增加判断:
JavaScriptif ( window.webkit && window.webkit.messageHandlers && window.webkit.messageHandlers.nativeBridge ) { window.webkit.messageHandlers.nativeBridge.postMessage({ action:"login" }); }
这样即使原生没有注入对象,也不会导致页面报错。
四、检查WKWebView加载时机
很多问题来自页面加载顺序。
例如:
HTML:
HTMLinitApp();