美文网首页
JS和OC交互

JS和OC交互

作者: 咔咔尼亜 | 来源:发表于2018-12-15 10:09 被阅读8次

    JavaScriptCore和原生页面交互


    主要主要总结一下利用JavaScriptCore和UIWebView交互过程中遇到的问题。分三部分讲解

    1. JS调用原生
    2. OC调用JS
    3. 传值

    JSContext可以将它视为一个盒子(字典),盒子中装了所有的webview加载的网页的代码(和H5的document对象好像),通过这个JSContext对象可以拿到盒子中的任意一个元素或者JS方法(通过方法名字符串),JSContext拿出来的东西 是JSValue对象。JSValue对象是对js中的对象或者方法进行的封装。

    JS调用原生方法

    首先导入JavaScriptCore,初始化webview,实现webview代理方法,然后再代理方法- (void)webViewDidFinishLoad:(UIWebView *)webView中实现初始化JSContext对象代码如下:

    //对JSContext对象进行初始化
        self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    
    1. 利用block进行的调用
        self.context[@"webAudio"] = ^(NSString *speakingWords){
            NSLog(@"speakingwords====%@",speakingWords);
        };
    

    其中webAudio为js中的方法名 block的参数为js调用webAudio方法的时候给webAudio方法传递的参数,相当于将js的方法直接用block替换了。所以在JS调用JS的webAudio方法的时候,实际是在调用block,OC中可以在block中实现调用OC的方法,完成JS调用OC方法。

    1. 利用协议JSExport
      一. 将JS中JS方法的调用者设置为控制器对象。
      二. 自定义一个协议继承自JSExport协议,并定义OC中将调用的方法
    self.context[@"wjyg"] = self;
    
    @protocol WebExpert <JSExport>
    JSExportAs(toPage, -(void)jumpToSpeakingView:(NSString*)passWords);
    @end
    

    JS代码如下

      function toPageForWJYG(data){
            try {
                window.wjyg && wjyg.toPage(data);
            } catch(e){
                alert(e.message);
            }
        }
    

    JS中通过调用wjyg对象的toPage方法进行传值,第一步将controller对象赋值给js中的wjyg对象,相当于将对象进行了替换。
    第二步,实现协议 将toPage方法替换为了controller中的-(void)jumpToSpeakingView:(NSString)passWords。
    之后js调用wjyg.toPage(data)的时候,相当于controller调用了
    controller的-(void)jumpToSpeakingView:(NSString
    )passWords方法,


    OC调用JS方法

    一 .通过利用context和JS方法名字符串拿到JSValue包装的JS方法(也就是JSValue对象)
    二 . JSValue对象调用JSValue的方法就可以了(主要方法是callWithArguments:)。

    JSValue   *permissionValue = self.context[@"getListenPermission"];
    [permissionValue callWithArguments:@[@"true"]];
    

    OC之间传值

    在以上的方法调用之间有值的传递。仔细看代码。



    JavaScriptBridge和OC交互

    JavaScriptBridge说白了就相当于一个中间人,注册方法和调用方法就像卖东西和买东西,注册方法相当于卖家告诉bridge自己有某个东西,调用方法就像是买家告诉bridge自己就想买某个东西


    需要在js中加入代码

    function setupWebViewJavascriptBridge(callback) {
            if (window.WebViewJavascriptBridge) { return callback(WebViewJavascriptBridge); }
            if (window.WVJBCallbacks) { return window.WVJBCallbacks.push(callback); }
            window.WVJBCallbacks = [callback];
            var WVJBIframe = document.createElement('iframe');
            WVJBIframe.style.display = 'none';
            WVJBIframe.src = 'https://__bridge_loaded__';
            document.documentElement.appendChild(WVJBIframe);
            setTimeout(function() { document.documentElement.removeChild(WVJBIframe) }, 0)
    }
    

    在OC中调用的时候注意一下问题

    1. 给webivew设置bridge需要在webview创建之后就可以(另外不能重复设置也就是如下代码只调用一次就行了)
    _bridge = [WebViewJavascriptBridge bridgeForWebView:_webView];
     [_bridge  setWebViewDelegate:self];
    
    1. JS调用原生的时候,原生register方法的时机(也就是registerhander的方法应该放在webviewloadfinish代理方法中).因为要等到所有js文件加载完成之后才能想bridge注册方法.

    2. js端调用代码的时候不能通过ID获取已存在的button变量并添加onclick事件,这样会导致客户端点击按钮的时候第一次点击没有效果(注册事件的回调block不走),可以在点击事件中直接调用

    setupWebViewJavascriptBridge(function(bridge) {
                    bridge.callHandler('checkLoginWithUrl',{'hrefStr':"http://www.baidu.com?"}, function(response) {
                    })
            })
            setupWebViewJavascriptBridge(function(bridge) {
                bridge.callHandler('checkLogin', function(response) {
                })
            })
    

    相关文章

      网友评论

          本文标题:JS和OC交互

          本文链接:https://www.haomeiwen.com/subject/ztwohqtx.html