关于UIWebView中OC与JavaScript交互

作者: 码痞 | 来源:发表于2015-10-26 23:31 被阅读1763次

    为什么要交互?

    在实际项目中往往会使用到页面中内嵌wap页的情况,这样做能减少开发工作量,且只要修改wap页就能同步改变iOS端页面的内容,很方便。虽然iOS

    实际工程中常希望在点击wap页面内容时不使用wap页本身的跳转,而是跳转到项目中的另一个页面,就需要在JS中调用iOS端中类似以下的方法进行跳转或执行一些其他操作

      [self.navigationController pushViewController:ViewController animated:YES];
    

    有时也有可能通过iOS端的方法来调用JS中的方法来实现一些功能
    所以就需要实现在JS和iOS端之间进行 交配 交互

    在iOS8中新增的WKWebView框架带有Nitro JavaScript引擎,正在逐步取代WebView框架,为了向下适配iOS7的用户所以工程里还是用了UIWebView。


    相关的iOS原生方法

    1.UIWebView的代理方法
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

    在WebView中的wap页将要载入内容时得到通知触发,返回NO则阻止加载内容,

    • 优点:简单易用,在页面跳转请求时进行iOS端的页面跳转,并返回NO阻止wap内的页面跳转
    • 缺点:无法识别不加载新内容的JS动作(点击按钮弹出对话框和提交等)
      这里比较推荐用方法1,方法2需要JS基础,不太懂得前端开发的程序员慎用

    2.运用JavaScriptCore框架进行交互

    • JS中调用OC方法
     //获取当前的JS环境
     JSContext* context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    //----------------------------------------------------------------------------------------------------------------
    //用block定义要被JS调用的方法
    NSNumber* (^do_something)(void) = ^(void){
        BOOL singleDog = [programmer isSingle];
        int someData = singleDog?1:-1; 
        return [NSNumber numberWithInt:someData];//数据类型应为Number,此时即为OC向JS传值
    };
    //在JS中添加了一个方法指针 do_something
    context[@"do_something"] = do_something;
    

    该方法常在以下UIWebView的代理方法中使用,在页面加载完毕时向JS中添加
    - (void)webViewDidFinishLoad:(UIWebView *)webView

    • OC中调用JS方法
     [myWebView stringByEvaluatingJavaScriptFromString:@"JS中的方法"];
    

    暂时不会写JS,具体例子请参考这里


    第三方框架 WebViewJavascriptBridge

    该框架的主要使用方法是在iOS端中先创建一个WebViewJavascriptBridge对象,并运用该对象实现交互

    首先要在JS中添加如下方法

    function connectWebViewJavascriptBridge(callback) {
    if (window.WebViewJavascriptBridge) {
        callback(WebViewJavascriptBridge)
    } else {
        document.addEventListener('WebViewJavascriptBridgeReady', function() {
                                  callback(WebViewJavascriptBridge)
                                  }, false)       
    }
    
     connectWebViewJavascriptBridge(function(bridge) {
     //注意,你的bridge函数都应写在这里面
     }
    
     //例如
    function doSomething(){
    connectWebViewJavascriptBridge(function(bridge) {
       bridge.init(function(message, yourCallback) {
          log('ObjC called testJavascriptHandler with', message)
    
           var responseData = { 'Javascript Says':'Right back atcha!' }
           log('JS responding with', responseData)
           responseCallback(responseData)
           })
        }
     }
    
    OC调用JS方法

    1.调用JS中bridge.init的方法

      //OC
      [_bridge send:@"The message sent from ObjC to JS" responseCallback:^(id response) {
        NSLog(@"sendMessage got response: %@", response);//这里的response是js方法中的data
    }];
    
    
     //对应调用js中的方法
     bridge.init(function(message, yourCallback) {
        log('ObjC called testJavascriptHandler with', message)
    
        var responseData = { 'Javascript Says':'Right back atcha!' }
        log('JS responding with', responseData)
        responseCallback(responseData)
     })
    

    2.调用JS中bridge.registerHandler方法,该方法可以注册方法名,通过注册名确认调用方法

     //OC
     [_bridge callHandler:@"注册名" data:data responseCallback:^(id response) {
        NSLog(@"testJavascriptHandler responded: %@", response);
    }];
    
     //对应调用的js中的方法
     bridge.registerHandler('注册名', function(data, responseCallback) {
            log('ObjC called testJavascriptHandler with', data)
    
            var responseData = { 'Javascript Says':'Right back atcha!' }
            log('JS responding with', responseData)
            responseCallback(responseData)
        })
    
    JS端调用OC端方法

    1.调用OC中创建bridge对象时定义时的方法

     //JS中
       bridge.send(data,function(response){
         log('这里是回调方法',response) //回调方法
       })
    
    
    
    //对应调用的OC中bridge初始化中设置的block方法
    _bridge = [WebViewJavascriptBridge bridgeForWebView:webView webViewDelegate:self handler:^(id data, WVJBResponseCallback responseCallback) {
        //do something...        
        NSLog(@"ObjC received message from JS: %@", data);//从js获得的参数
        responseCallback(@"Response");//Response to js
    }];
    

    2.通过方法名调用OC中bridge的注册方法

     //JS中
     bridge.callHandler('注册名', {'foo': 'bar'}, function(response) {
         log('JS got response', response)
     })
    
     //对应调用的OC中的bridge注册的方法
    [_bridge registerHandler:@"注册名" handler:^(id data, WVJBResponseCallback responseCallback) {
        NSLog(@"testObjcCallback called: %@", data);//从js获取的参数
    
        responseCallback(@"Response");//
    }];
    

    参考资料:
    WebViewJavascriptBridge源码分析
    UIWebView与JS的深度交互

    相关文章

      网友评论

      本文标题:关于UIWebView中OC与JavaScript交互

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