• 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

  • 相关阅读:
    设计模式系列
    【ABAP系列】SAP ABAP 关于FUNCTION-POOL的理解
    【MM系列】SAP S/4 HANA 1511的BP角色创建及供应商数据的创建方法
    【ABAP系列】SAP ABAP 动态指针
    【HR系列】SAP HR PA信息类型的创建与增强
    【HANA系列】SAP UI5上传图片 用XSJS存储在HANA中的方法
    【HANA系列】SAP Vora(SAP HANA和Hadoop)简析
    【MM系列】SAP SAP库龄报表逻辑理解
    【HANA系列】SAP HANA XS Administration Tool登录参数设置
    【ABAP系列】SAP 一个完整的SAP的Abap例子(idoc,edi文件的相互转换)
  • 原文地址:https://www.cnblogs.com/cocoajin/p/5999311.html
Copyright © 2020-2023  润新知