OC中JavaScriptCore使用的两个问题

1、iOS7及以后的版本中提供了JavaScriptSore框架,极大的方便了OC与JS的交互
2、基本使用参考: Object-C与JavaScript交互的两种方式
3、使用过程中存在一些问题,这里拿两个最为常见的问题进行分析
4.1、如果没有JS调用时没有该方法,如果捕获异常
A、JS调用OC方法时,如果不存在该方法不会造成程序崩溃,只是没任何反应而已,哪里可以看出来呢?
B、其实JSContext已经提供了一个方法,只是平时没有用,JSContext有条属性

1
2
3
4
5
6
7
8
9
10
11
/*!
@property
@discussion If a call to an API function results in an uncaught JavaScript exception, the
 <code>exceptionHandler</code> block will be invoked. The default implementation for the
 exception handler will store the exception to the exception property on
 context. As a consequence the default behaviour is for unhandled exceptions
 occurring within a callback from JavaScript to be rethrown upon return.
 Setting this value to nil will result in all uncaught exceptions thrown from
 the API being silently consumed.
*/
@property (copy) void(^exceptionHandler)(JSContext *context, JSValue *exception);


C、这条属性就是用来捕获异常的,我们可以直接通过set方法来捕获异常

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    [SAApp setNetworkActivityIndicatorVisible:NO];
    [self.JSContext evaluateScript:@"webView.check()"];
}
- (JSContext *)JSContext
{
    if (self-&gt;_JSContext == nil){
        self-&gt;_JSContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        [self-&gt;_JSContext setObject:self.javaScript forKeyedSubscript:@"webView"];
        [self-&gt;_JSContext setExceptionHandler:^(JSContext *context, JSValue *value) {
            context.exception = value;
            SALog(@"JS错误信息****\n%@****", value);
        }];
    }
    return self-&gt;_JSContext;
}

D、如果调用了不存在的check()方法则输出以下异常信息:

1
2
2016-03-17 17:39:00.755 fisher[8500:262650] __26-[SAWebViewCtrl JSContext]_block_invoke-155:JS错误信息****
TypeError: webView.check is not a function. (In 'webView.check()', 'webView.check' is undefined)****

4.2、UIWebView加载的第一个页面JS调用本地方法没有问题,但如果跳转到了一个新的页面后,JS调用本地方法失效?

A、如上例所示,如果我们如果进入了下一个页面,再调用本地方法就会有如下错误信息

1
2
2016-03-17 17:44:31.465 fisher[8537:267499] __26-[SAWebViewCtrl JSContext]_block_invoke-152:JS错误信息****
ReferenceError: Can't find variable: webView****

B、从以上代码来看,JSContext是一种懒加载模式,如果使用了JSContext则会初始化并将其以”webView”这个描述注入到全局JS中去,所以加载的第一个页面是好使的,可页面跳转了为什么就不行了?!
C、我们想想网页的加载方式,有JS基础的童鞋应该知道,JS是可以直接写在中以标签存在的,或者通过link进来的;
D、我们的注入可以理解成是在页面加载完毕后临时写到这个标签中去的,那么页面刷新了或跳转到新页面了会怎样?
E、答案是当前网页源代码中之前的JS已经没有了,我们注入的那段JS代码被刷新掉了,所以要重新注入!
F、不需要重新创建JSContext对象,只需要执行注入即可,最好是将注入方法写在代理方法中

1
2
3
4
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    [self.JSContext setObject:self.javaScript forKeyedSubscript:@"webView"];
}

G、大功造成,不信试试看

Leave a Reply