iOS7以后,苹果加入了JSContext来处理JavaScript,实现h5页面和原生的交互。之前项目中经常会用到JSContext,也遇到了很多问题,现在刚好有时间,把遇到的问题正好记录下来。
一.JSContext循环引用导致不释放的问题
1.1 遇到的问题
self.jsContext = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"app"] = weakSelf;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue;
NSLog(@"异常信息:%@", exceptionValue);
};
如上代码所示,JSContext引用了self,self又引用了JSContext,彼此等待对方造成了循环引用的问题,尽管使用了weakSelf,还是不会解除这种状态。
1.2 解决方法
本人是通过创建一个中间对象来实现的,代码如下:
self.jsContext = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
self.jsContext[@"app"] = _weakWebJSExportDelegate;
self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
context.exception = exceptionValue;
NSLog(@"异常信息:%@", exceptionValue);
};
_weakWebJSExportDelegate的创建方法,在viewDidLoad创建
_weakWebJSExportDelegate = [[WeakWebJSExportDelegate alloc] initWithDelegate:self];
WeakWebJSExportDelegate的实现
454FB2D1-14DC-4761-962C-F1935D150A92.png
如上图所示,BTNVSetTitle是h5调用app的方法,引入Back2ObjcDelegate是为了让该方法的执行还是在webview里面实现。
二.UIWebview调用reload导致JSContext失效的问题
2.1 遇到的问题
当页面刷新或者跳转新页面,shouldStartLoadWith与webViewDidStartLoad获取的均为上一个页面的JSContext。而webviewDisFinishLoad触发的时候,获取虽然是正确的JSContext,但是此时页面已经加载完毕,js方法已经调用完了,获取到正确的值也没用了,所以就导致了JSContext失效的问题。
2.2 解决方法
需要刷新的时候重新创建一个webview,同时删掉老的webview,这样新的webview获取JSContext的时候不会获取到老的,那么正确的JSContext就能正确设置JS对象。
网友评论