年年有"余"

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 3569|回复: 5

[项目经验] OC中JavaScriptCore使用的两个问题

[复制链接]
  • TA的每日心情
    奋斗
    2022-12-13 21:26
  • 签到天数: 371 天

    [LV.9]以坛为家II

    发表于 2016-3-17 17:46:32 | 显示全部楼层 |阅读模式
    1、iOS7及以后的版本中提供了JavaScriptSore框架,极大的方便了OC与JS的交互
    2、基本使用参考:http://www.yusian.com/thread-11159-1-1.html
    3、使用过程中存在一些问题,这里拿两个最为常见的问题进行分析
    4.1、如果没有JS调用时没有该方法,如果捕获异常
    A、JS调用OC方法时,如果不存在该方法不会造成程序崩溃,只是没任何反应而已,哪里可以看出来呢?
    B、其实JSContext已经提供了一个方法,只是平时没有用,JSContext有条属性
    [Objective-C] 纯文本查看 复制代码
    /*!
    @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方法来捕获异常
    [Objective-C] 纯文本查看 复制代码
    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        [SAApp setNetworkActivityIndicatorVisible:NO];
        [self.JSContext evaluateScript:@"webView.check()"];
    }
    - (JSContext *)JSContext
    {
        if (self->_JSContext == nil){
            self->_JSContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
            [self->_JSContext setObject:self.javaScript forKeyedSubscript:@"webView"];
            [self->_JSContext setExceptionHandler:^(JSContext *context, JSValue *value) {
                context.exception = value;
                SALog(@"JS错误信息****\n%@****", value);
            }];
        }
        return self->_JSContext;
    }
    D、如果调用了不存在的check()方法则输出以下异常信息:
    [Objective-C] 纯文本查看 复制代码
    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、如上例所示,如果我们如果进入了下一个页面,再调用本地方法就会有如下错误信息
    [Objective-C] 纯文本查看 复制代码
    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是可以直接写在<head>中以<script></script>标签存在的,或者通过link进来的;
    D、我们的注入可以理解成是在页面加载完毕后临时写到这个标签中去的,那么页面刷新了或跳转到新页面了会怎样?
    E、答案是当前网页源代码中之前的JS已经没有了,我们注入的那段JS代码被刷新掉了,所以要重新注入!
    F、不需要重新创建JSContext对象,只需要执行注入即可,最好是将注入方法写在代理方法中
    [Objective-C] 纯文本查看 复制代码
    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        [self.JSContext setObject:self.javaScript forKeyedSubscript:@"webView"];
    }
    G、大功造成,不信试试看

    该用户从未签到

    发表于 2016-3-27 22:44:42 | 显示全部楼层
        [self->_JSContext setObject:self.javaScript forKeyedSubscript:@"webView"];按这样注入也是不行,有具体的demo提供参考吗?最好友js调用的代码
  • TA的每日心情
    倒霉
    2020-11-28 20:31
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    发表于 2016-3-28 09:32:18 | 显示全部楼层
    A-Hing 发表于 2016-3-27 22:44
    [self->_JSContext setObject:self.javaScript forKeyedSubscript"webView"];按这样注入也是不行,有 ...
    写错了,应该是[self.JSContext setObject:self.javaScript forKeyedSubscript:@"webView"];
    [HTML] 纯文本查看 复制代码
    <html>
    	<body>
    		<button oncli ck="webView.share()">分享</button>
    	</body>
    </html>
    调用- (void)share方法



    该用户从未签到

    发表于 2016-3-29 17:10:24 | 显示全部楼层
    admin 发表于 2016-3-28 09:32
    写错了,应该是[self.JSContext setObject:self.javaScript forKeyedSubscript"webView"];
    [mw_shl_co ...

    这个会涉及js的加载顺序吧,如果用一个button去出发js调用oc是可以成功的,但如果是没有button的点击事件呢?  换成有js的html加载过程中就主动去加载oc方法呢?这种情况要怎么做呢?
  • TA的每日心情
    倒霉
    2020-11-28 20:31
  • 签到天数: 18 天

    [LV.4]偶尔看看III

    发表于 2016-3-29 18:14:04 | 显示全部楼层
    A-Hing 发表于 2016-3-29 17:10
    这个会涉及js的加载顺序吧,如果用一个button去出发js调用oc是可以成功的,但如果是没有button的点击事件 ...

    那要看你什么时候注入了,前面执行[self.JSContext setObject:self.javaScript forKeyedSubscript"webView"];
    是在方法- (void)webViewDidFinishLoad:(UIWebView *)webView中,说明等页面加载完毕后再注入我们的JS代码,如果在页面加载完毕之前页面就需要调用,那在这里注入是不合适的
    但可以在- (void)webViewDidStartLoad:(UIWebView *)webView
    这个方法中执行[self.JSContext setObject:self.javaScript forKeyedSubscript"webView"];
    即要页面加载之前就注入

    该用户从未签到

    发表于 2016-3-30 17:30:47 | 显示全部楼层
    admin 发表于 2016-3-29 18:14
    那要看你什么时候注入了,前面执行[self.JSContext setObject:self.javaScript forKeyedSubscript"webVie ...

    恩恩,受教了,感谢
    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    手机版|小黑屋|Archiver|iOS开发笔记 ( 湘ICP备14010846号 )

    GMT+8, 2024-4-16 22:12 , Processed in 0.050283 second(s), 18 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表