美文网首页iOS小筑PerhapYs的OC学习日记iOS知识
iOS开发-基于原生JS与OC方法互相调用并传值(附HTML代码

iOS开发-基于原生JS与OC方法互相调用并传值(附HTML代码

作者: TianBai | 来源:发表于2016-06-12 22:50 被阅读16437次

    最近项目里面有有个商品活动界面,要与web端传值,将用户在网页点击的商品id 传给客户端,也就是js交互,其实再说明白一点就是方法的互相调用而已。

    本文叙述下如何进行原生的JavaScript交互

    本文包括JS调用OC方法并传值,OC调用JS方法并传值

    本来想把html放进服务器里面,然后访问,但是觉得如果html在本地加载更有助于理解,特把html放进项目里

    HTML代码

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="UTF-8">
    </head>
    <body>
    <div style="margin-top: 20px">
    <h2>JS与OC交互</h2>
    <input type="button" value="唤起本地方法(call)" onclick="tianbai.call()">
    </div>
    <div>
    <input type="button" value="唤起getCall:(NSString *)callString传值" onclick="call()">
    </div>
    
    <script>
        
        
        
    var call = function()
    {
        var callInfo = JSON.stringify({"jianshu": "http://www.jianshu.com/users/55c8fdc3c6e7/latest_articles"});
            tianbai.getCall(callInfo);
    }
    
    var Callback = function(str)
    {
        alert(str);
    }
    var alerCallback = function()
    {
        alert('成功');
    }
    </script>
    </body>
    </html>
    

    上面html的代码:建立了两个button

    第一个button绑定了 tianbai.call() 方法,这里 tianbai 是一个对象,这个对象的作用下面OC代码中会说明, tianbai.call() 代表 tianbai 对象调用 call() 方法

    第二个button绑定了 call() 的方法,调用的是下面JavaScript中的 call() 方法,在 JavaScript 的 call() 里面,定义一个 callInfo 参数,方法中 tianbai.getCall(callInfo) 代表 tianbai 对象调用 getCall 方法并传参数 callInfo ,下面两个方法是OC调用JavaScript方法,其中Callback传回str,alerCallback为OC仅调用JavaScript方法!

    OC代码

    demo采用原生的JavaScriptCore类

    引入三个名词:

    1. JSContext:给JavaScript提供运行的上下文环境
    2. JSValue:JavaScript和Objective-C数据和方法的桥梁
    3. JSExport:这是一个协议,如果采用协议的方法交互,自己定义的协议必须遵守此协议

    ViewController.h中的代码(代码过长,方法说明都在注释里)

    #import <UIKit/UIKit.h>
    //导入头文件
    #import <JavaScriptCore/JavaScriptCore.h>
    
    @protocol JSObjcDelegate <JSExport>
    //tianbai对象调用的JavaScript方法,必须声明!!!
    - (void)call;
    - (void)getCall:(NSString *)callString;
    
    @end
    @interface ViewController : UIViewController<UIWebViewDelegate,JSObjcDelegate>
    @property (nonatomic, strong) JSContext *jsContext;
    @property (strong, nonatomic)  UIWebView *webView;
    
    @end
    

    ViewController.m中的代码(代码过长,方法说明都在注释里)

    JavaScriptCore中web页面调用原生应用的方法可以用Delegate或Block两种方法,此文以按Delegate讲解。

    设置webView

    self.webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 20, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
        self.webView.delegate = self;
        //从本地加载html文件
        NSString* path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
        NSURL* url = [NSURL fileURLWithPath:path];
        NSURLRequest* request = [NSURLRequest requestWithURL:url] ;
        [self.webView loadRequest:request];
        
        [self.view addSubview:self.webView];
    

    JavaScript的tianbai是一个对象,充当原生应用和web页面之间的一个桥梁。用来调用方法

    webview加载完成调用代理

    - (void)webViewDidFinishLoad:(UIWebView *)webView {
    
          // 设置javaScriptContext上下文
        self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        //将tianbai对象指向自身
        self.jsContext[@"tianbai"] = self;
        self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
            context.exception = exceptionValue;
            NSLog(@"异常信息:%@", exceptionValue);
        };
    }
    

    将对象指向自身后,如果调用 tianbai.call() 会响应下面的方法,OC方法中调用js中的Callback方法,并传值

    - (void)call{
        NSLog(@"call");
        // 之后在回调JavaScript的方法Callback把内容传出去
        JSValue *Callback = self.jsContext[@"Callback"];
        //传值给web端
        [Callback callWithArguments:@[@"唤起本地OC回调完成"]];
    }
    

    将对象指向自身后,如果调用 tianbai.getCall(callInfo) 会响应下面的方法,OC方法中仅调用JavaScript中的alerCallback方法

    - (void)getCall:(NSString *)callString{
        NSLog(@"Get:%@", callString);
        // 成功回调JavaScript的方法Callback
        JSValue *Callback = self.jsContext[@"alerCallback"];
        [Callback callWithArguments:nil];
    }
    
    

    将对象指向自身后,还可以向html注入js

    - (void)alert{
    
        // 直接添加提示框
        NSString *str = @"alert('OC添加JS提示成功')";
        [self.jsContext evaluateScript:str];
    
    }
    
    

    Demo地址:点击下载

    相关文章

      网友评论

      • 咖啡bu加糖:你的项目能运行,拖进我的工程却不能调用,是因为多个界面有这个协议就不行了么,求回答啊
      • 超棒的程序员:你好,我想问下JavaScript的tianbai是一个对象,这个对象怎么定义?
      • TigerNong:你有没有发现,当你加载完之后,再退出当前加载有webView的控制器时,没有调用当前控制器的dealloc方法,也就是存在有循环引用!
        MemoryReload:The retain cycle starts, after this piece of shit "self.jsContext[@"tianbai"] = self;" executed. So if you are a wise man, do not let the JS context retain your controller! Because your controller has an strong reference to your webView instance. And of course, it has an indirect reference to your JS context. If you let the JS context retain your controller, congratulations!
      • Joy___:厉害
      • 香橙柚子:你好,请问你这个调用getcall的时候,传递的是一个参数,能不能传递两个参数.当传递两个参数的是方法名就变了,接受不到了
      • f9752836b891:您好,我也遇到同样的问题。我们后台那边回调我们iOS的方法时,无法实现自动调用,只能通过点击才能回调,安卓那边是可以自动调用的;请问你这个问题解决没?谢谢!
        2d723cb33cab:@小小聪明屋123 我也遇见这样的问题了,请问你解决了么?
        f9752836b891:@TianBai 这个方法是要后台来调用的,我们现在是加载后台的一个链接地址,当用户在这个网页上面执行到某一个步骤时,比如当用户点击了某个按钮,后台那边要处理一些他自己的逻辑代码,然后再调用我们前端这个方法;现在的问题是后台那边没有调到我们前端的这个方法里面来;但是:如果只是点击网页上的某个按钮是可以回调到我们的方法里面来的。
        TianBai:@小小聪明屋123 可以
      • 精灵物联网:你好,想问一下,网页加载完成,如何实现自动调用这个方法,而不是通过点击事件。tianbai.call()
        TianBai:第一种:你让网页唤起这个方法
        第二种:你在网页加载完成之后,手动调用这个方法
        精灵物联网:@TianBai <input type="button" value="js调用oc本地方法(call)" onclick="tianbai.call()">
        这个是点击执行,怎样让他自动调用
        TianBai:@woofer 网页加载完成代理里面加上[self methodname]

      本文标题:iOS开发-基于原生JS与OC方法互相调用并传值(附HTML代码

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