OC和JS交互

作者: 大师的书 | 来源:发表于2019-05-24 12:08 被阅读1次

前言

最近有朋友问我OC和JS交互的问题,我又翻开看了一下之前的代码,发现了一个对jscore理解非常方便的方法,分享给大家。这篇文章我主要讲js调用OC,OC调用js不在该范围内

JavaScriptCore做OC交互的方法

主要分为两种:

  1. 使用block在js代码里注入方法
  2. 使用JSExport协议在js代码里注入一个对象

方法一

使用Block

OC代码:

controller.m

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    context[@"testClick"] = ^(NSString * p1, NSString * p2) {
        NSLog(@"p1:%@, p2:%@", p1, p2);
    };
}  
  1. 这里我在- (void)webViewDidFinishLoad:(UIWebView *)webViewwebview的加载结束代理方法中调用了JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];拿到上下文。
  2. 然后给JSContext上下文添加了testClickblock,这个block有两个参数。

JS代码:

<html>
<head>
    <script>
        function func3Click() {
            testClick("参数一", "参数二");
        }
    </script>
</head>
<body>

    <button onclick="func3Click()">button3</button>
    
</body>
</html>
  1. 在js代码中大家可以注意到testClick("参数一", "参数二");对应的是OC中的 context[@"testClick"] = ^(NSStri ...。这样就完成了js和OC的交互。

方法二

使用JSExport协议

OC代码:

JSHandler.h

@import JavaScriptCore;

@protocol JSHandlerDelegate <JSExport>

- (void)twoparamWithOne:(NSString *)p1 two:(NSString *)p2;

@end

@interface JSHandler : NSObject<JSHandlerDelegate>

@end
JSHandler.m

@implementation JSHandler

- (void)twoparamWithOne:(NSString *)p1 two:(NSString *)p2 {
    NSLog(@"p1:%@, p2:%@", p1, p2);
}

@end
controller.m

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    JSContext *context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    JSHandler * handler = [[JSHandler alloc] init];
    context[@"abchaha"] = handler;
}  

我将关键代码抽离了出来

  1. 我创建了一个JSHandler类,该类有一个- (void)twoparamWithOne:(NSString *)p1 two:(NSString *)p2的方法,用来供js调用。
  2. 在我的controller中有一个webview,- (void)webViewDidFinishLoad:(UIWebView *)webView是webview的加载结束代理方法。我该方法中通过[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"]拿到方法拿到jscore的上下文变量(用来操作js)。
  3. contextp[@"abchaha"] = handler,来将我创建的JSContext对象传给jscore,这样在js里就可以使用abchaha这个变量来调用JSHandler的协议里声明的方法了。下面我们来看看JS部分的代码。

JS代码:

<html>
<head>
    <script>
        function func3Click() {
            abchaha.twoparamWithOneTwo("参数一", "参数二");
        }
    </script>
</head>
<body>

    <button onclick="func3Click()">button3</button>
    
</body>
</html>

注意这里abchaha.twoparamWithOneTwo("参数一", "参数二");这行是关键代码。

  1. 大家可以看到,OC中 contextp[@"abchaha"] = handler 的key对应了js中abchaha.twoparamWithOneTwo("参数一", "参数二");
  2. OC协议中的方法- (void)twoparamWithOne:(NSString *)p1two:(NSString *)p2;,对应了js中的twoparamWithOne Two("参数一", "参数二");,在js中使用驼峰原则就可以调用到OC协议中的方法。

JavaScriptCore在干什么

上述两个方法方法一明显比方法二要简单的多,但其实不知道大家有没有发现一个规律。那就是他们都是使用documentView.webView.mainFrame.javaScriptContext拿到了JSContext上下文,我们可以用这个JSContext使用[]给他设置字段。

其实可以这样理解。下面我用js和oc对应的代码来做一下我的理解。

方法一

  1. 当我们的webview代理里什么都没写的时候,是这样的。
JS

OC

  1. 当我们在webview代理里使用context[@"abchaha"] = handler;设置实现JSExport协议的类的对象时,是这样的。
JS

var abchaha = 实现JSExport的对象;
OC

id <继承JSExport的协议> abchaha = 实现JSExport的对象;
  1. 当我们在JS里调用abchaha.twoparamWithOneTwo("参数一", "参数二");的时候,是这样的。
JS

var abchaha = 实现JSExport的对象;
abchaha.twoparamWithOneTwo("参数一", "参数二");
OC

id <继承JSExport的协议> abchaha = 实现JSExport的对象;
[abchaha twoparamWithOne:@"参数一" two:@"参数二"];

方法二

  1. 什么都没写的时候就不展示了,就是NoCode。

  2. 当我们在webview代理里使用context[@"testClick"] = ^(NSStri ...设置Block的时候,是这样的。

JS

var testClick = (var p1){
  ...
}
OC

void(^ testClick)(NSString * p1, NSString * p2) = ^() {
  ...
};
  1. 当我们在JS里调用abchaha.twoparamWithOneTwo("参数一", "参数二");的时候,是这样的。
JS

var testClick = (var p1) {
  ...
}
testClick("参数一", "参数二");
OC

void(^ testClick)(NSString * p1, NSString * p2) = ^() {
  ...
};
testClick(@"参数一", @"参数二");

总结

其实方法一方法二都是拿到JSContext对象以后,给它设置变量,你可以理解为在往js里写代码。

方法一是给了js一个我们声明好协议的对象,让js可以直接调用对象协议中的方法。而方法二是给js设置了一个闭包(block)让js可以回调我们的方法。

我甚至可以使用context[@"aStr"] = @"哈哈哈";直接给js设置一个字符串,然后在js中使用alert(aStr);来弹出它。

至此,我建议大家可以把JSContext按它的本意来理解,这个JSContext就是拿到js上下文,然后给js代码通过[]设置变量

相关文章

网友评论

    本文标题:OC和JS交互

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