zoukankan      html  css  js  c++  java
  • iOS中JS 与OC的交互(JavaScriptCore.framework)

    iOS中实现js与oc的交互,目前网上也有不少流行的开源解决方案;

    如:react native

    当然一些轻量级的任务使用系统提供的UIWebView 以及JavaScriptCore.framework 里面提供的api就能快速满足的。

    方式一:iOS6上使用UIWebView 拦截url方式

    以下是演示的js和oc端的代码

    <html>
    <head><title>JAAndOC1</title></head>
    <script>
            function sdkhi()
            {
                alert("hello world!");
            }
    
            function sdkhito(name)
            {
                alert("hello to "+name);
            }
        
    </script>
    <body>
        
        <h1>hello world</h1>
        <h1>hello world</h1>
        <h1>hello world</h1>
        <h1>hello world</h1>
    
        <h1><a href="TCSDK://START?name=cc&age=18&phone=10086">START</a></h1>
        <h1><a href="javascript:sdkhi()">SDKHI</a></h1>
    
    </body>
    
    </html>
    View Code
    @interface ViewController ()<UIWebViewDelegate>
    {
        UIWebView *theWeb;
    }
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        theWeb = [[UIWebView alloc]initWithFrame:self.view.bounds];
        theWeb.scalesPageToFit = YES;
        theWeb.delegate = self;
        [self.view addSubview:theWeb];
        
        
        //本示例方法适用于iOS 6 +
        
        NSURL *reqUrl = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"js1.html" ofType:nil]];
        [theWeb loadRequest:[NSURLRequest requestWithURL:reqUrl]];
        
        
        
        
        UIButton *clickBtn = [UIButton buttonWithType:UIButtonTypeCustom];
        clickBtn.frame = CGRectMake(100, 100, 100, 100);
        [clickBtn setTitle:@"clisk" forState:0];
        [clickBtn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        [self.view addSubview:clickBtn];
        [clickBtn addTarget:self action:@selector(clickToCloseAlert) forControlEvents:UIControlEventTouchUpInside];
        
        
    
    }
    
    //OC调JS 并传参数
    - (void)clickToCloseAlert
    {
        //在弹出的alert中可能会有来自 xxx.html 字样 (百度去掉)
        [theWeb stringByEvaluatingJavaScriptFromString:@"sdkhito('cc')"];
    }
    
    
    
    //JS 调 OC 并传参数
    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
    {
        
        //访问如下自定义协议连接
        //request.URL   tcsdk://START?name=cc&age=18&phone=10086
        //request.URL.scheme   tcsdk 取出协议
        //request.URL.host     START 取出host
        //request.URL.query name=cc&age=18&phone=10086  取出参数
        NSLog(@"%@",request.URL);
        NSLog(@"%@",request.URL.scheme);
        
    
        
        return YES;
    }
    View Code

    1. OC 调用js代码主要通过如下接口 

        [theWeb stringByEvaluatingJavaScriptFromString:@"sdkhito('cc')"];

         流程:iOS的UIWebView 加载 包含js的网页;在js中定义好函数接口;

          然后在oc上就可以通过上面接口直接调用的;

    2. JS 调用OC 主要通过UIWebView的代理方法shouldStartLoadWithRequest 拦截URL

    //JS 调 OC 并传参数

    - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType

    {

        

        //访问如下自定义协议连接

        //request.URL   tcsdk://START?name=cc&age=18&phone=10086

        //request.URL.scheme   tcsdk 取出协议

        //request.URL.host     START 取出host

        //request.URL.query name=cc&age=18&phone=10086  取出参数

        NSLog(@"%@",request.URL);

        NSLog(@"%@",request.URL.scheme);

        

        return YES;

    }

      流程:iOS UIWebView 加载包含js的网页;在网页中用<a> 标签名其他跳转方式改变url的操作;

       然后在代理中通过拆分url的结构,分别取出协议,host,参数等;来达到js调用oc方法的的目的。

      问题:通过url传参有限制

    方式二:iOS7之后使用 JavaScriptCore.framework

     该框架提供完整的js运行环境,在处理oc与js的交互中非常的方法;

    如下测试代码

    <html>
        <head><title>JAAndOC2</title></head>
        <script>
            
            //以下方法由oc 调用 js
            function sdkhi3TO(name)
            {
                alert("hello world2!"+name);
            }
        
            function sdkhi2()
            {
                alert("hello world2!");
            }
        
            function sdkhito(name)
            {
                alert("hello to "+name);
            }
            
            </script>
        <body>
            
            <h1>hello world</h1>
            <h1>hello world</h1>
            <h1>hello world</h1>
            <h1>hello world</h1>
            
            <h1><a href="TCSDK://START?name=cc&age=18&phone=10086">START</a></h1>
            <h1><a href="javascript:sdkhi2()">SDKHI</a></h1>
            
            <!-- 以下由js 调用oc 的方法 -->
            <h1><a href="javascript:ocsayhi('abc')">OCHI</a></h1>
            <h1><a href="javascript:alert(pl.fullyName())">OCHI</a></h1>
    
        </body>
        
    </html>
    View Code
    #import "ViewController.h"
    #import <JavaScriptCore/JavaScriptCore.h>
    #import "Person.h"
    
    @interface ViewController ()<UIWebViewDelegate>
    {
        UIWebView *theWeb;
        JSContext *jsCXT;
    }
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        //以下使用javascriptcore.framewordk
        
        //适用于iOS7.0
        
        theWeb = [[UIWebView alloc]initWithFrame:self.view.bounds];
        theWeb.scalesPageToFit = YES;
        theWeb.delegate = self;
        [self.view addSubview:theWeb];
        
        NSURL *reqUrl = [NSURL URLWithString:[[NSBundle mainBundle] pathForResource:@"js2.html" ofType:nil]];
        [theWeb loadRequest:[NSURLRequest requestWithURL:reqUrl]];
    
    
    }
    
    - (void)webViewDidFinishLoad:(UIWebView *)webView
    {
        //使用webview的js执行环境
        jsCXT = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
        
        //异常处理
        jsCXT.exceptionHandler =
        ^(JSContext *context, JSValue *exceptionValue)
        {
            context.exception = exceptionValue;
            NSLog(@"%@", exceptionValue);
        };
        
        
        
        //OC 调用JS
        //[jsCXT[@"sdkhi2"] callWithArguments:nil];
        //sdkhito
        //[jsCXT[@"sdkhito"] callWithArguments:@[@"aa"]];
        
        
        //注册一个方法由js调用
        jsCXT[@"ocsayhi"] = ^(NSString *name) {
            NSLog(@"say hi to %@",name);
        };
        
        
        Person *pp = [[Person alloc]init];
        pp.firstName = @"cc";
        pp.lastName = @"j";
        pp.site = @"baidu.com";
        jsCXT[@"pl"] = pp;
        
        
        [jsCXT evaluateScript:@"alert(pl.fullyName())"];
        
        
    }
    View Code
    #import <Foundation/Foundation.h>
    #import <JavaScriptCore/JavaScriptCore.h>
    @protocol PersonPtl <JSExport>
    
    @property (nonatomic,copy)NSString *site;
    /**
     对于多参数的方法,JavaScriptCore的转换方式将Objective-C的方法每个部分都合并在一起,冒号后的字母变为大写并移除冒号。比如下边协议中的方法,在JavaScript调用就是:doFooWithBar(foo, bar);
     
     **/
    - (NSString *)fullyName;
    
    @end
    
    @interface Person : NSObject<PersonPtl>
    
    @property (nonatomic, copy) NSString *firstName;
    @property (nonatomic, copy) NSString *lastName;
    
    
    @end
    View Code
    #import "Person.h"
    
    @implementation Person
    
    @synthesize site;
    
    - (NSString *)fullyName
    {
        return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
    
    }
    
    @end
    View Code

    1. OC调用js  

       流程我们创建UIWebView 在 代理中获取当前页面的js环境;就是JSContext

        jsCXT = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

      然后在网页js中定义的方法,在这里我们就可以直接调用了;

        //OC 调用JS

        [jsCXT[@"sdkhi2"] callWithArguments:nil];

            [jsCXT[@"sdkhito"] callWithArguments:@[@"aa"]];

     

    2. JS 调用 OC

       这里有两个方式,我们可以通过block的方法在oc里为js 注入一下方法,让js调用 

        //注册一个方法由js调用

        jsCXT[@"ocsayhi"] = ^(NSString *name) {

            NSLog(@"say hi to %@",name);

        };

      

       另外一个方法,稍麻烦一点,我们需要先声明协议,然后实现协议方法;通过JSExport 来暴露给JS环境调用

       如上面的代码中的Person类;

       调用方式:

        Person *pp = [[Person alloc]init];

        pp.firstName = @"cc";

        pp.lastName = @"j";

        pp.site = @"baidu.com";

        jsCXT[@"pl"] = pp;

        

       //以下是在当前jscxt中执行代码,当然网页js中也可以直接写 

        [jsCXT evaluateScript:@"alert(pl.fullyName())"];

    最后完整示例工程:

    https://github.com/cocoajin/TDDDemo/tree/master/JSAndOC

    参考:http://www.skyfox.org/ios-wkwebview-cookie-opration.html

  • 相关阅读:
    JDBC与JAVA数据库编程
    Java中的网络编程
    OracleDBA之表管理
    OracleDBA之用户管理
    OracleDBA之数据库管理
    Java中的多线程
    JavaSE高级之GUI编程
    JavaSE高级之集合类
    Java面向对象练习
    Java基本语法练习
  • 原文地址:https://www.cnblogs.com/cocoajin/p/5999311.html
Copyright © 2011-2022 走看看