JS与原生OC交互通信(一)

JavaScript与原生通信

  • UIWebView
  • WKWebView
  • JavaScripCore
  • 第三方库

JS和OC的交互分为两种方式:JS调用OC和OC调用JS,一般的原则是如果JS想传值给OC就用JS调用OC,相反则用OC调用JS

UIWebView

1.JS调用OC

通过UIWebView的代理方法拦截URL

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

当UIWebView在加载之前或者进行网页重定向的会调用这个代理方法,JS调用OC的就这这个代理方法里return YESUIWebView会继续跳转加载,return NO可拦截UIWebView的跳转,例如用UIWebView唤起支付宝客户端 :

- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString* reqUrl = request.URL.absoluteString;
    if ([reqUrl hasPrefix:@"alipays://"] || [reqUrl hasPrefix:@"alipay://"]) {
        [[UIApplication sharedApplication]openURL:request.URL];
        return NO;
    }
    return YES;
}

alipays://为支付宝唤起的协议,当加载支付宝支付的URL时,只需要拦截request.URL是否包含此协议,若包含我们只需通过[[UIApplication sharedApplication]openURL:request.URL]打开这个URL,若安装了支付宝就会唤起支付宝。

我们再来写一个本地h5界面,来看看具体交互。

JS代码:





    



    UIWebView JS 交互
    

OC代码:

初始化UIWebView,加载本地HTML

    UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
    NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
    [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:path]]];
    webView.delegate = self;
    [self.view addSubview:webView];

代理方法:

- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *url = request.URL.absoluteString;
    if ([url containsString:@"obj://regist"]) {
       UIAlertController *alert =  [UIAlertController alertControllerWithTitle:@"开始注册" message:@"注册" preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        [self presentViewController:alert animated:YES completion:nil];
        return NO;
    }
    return YES;
}
2017-12-21 17_46_41.gif

如图运行效果,当我们点击注册的时候,就会重定向我们自定义的URLobj://regist,UIWebView的代理方法就会调用,然后就如上述支付宝一样,拦截后return NO,弹出警告框,当然也可以传递参数给Native。

2.OC调用JS

OC最简单就是通过URL传递参数,跟GET请求一样拼接在后面,

OC还可以通过以下方法直接调取JS并传递参数方法如下

- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

还用上述的本地的HTML来演示,我需要在JS中添加一个方法nativeCall
JS部分如下:





    



    UIWebView JS 交互
    

OC代理方法

- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *url = request.URL.absoluteString;
    if ([url containsString:@"obj://login"]) {
        NSString *message = [NSString stringWithFormat:@"nativeCall('%@')", @"hello javascript"];
        [theWebView stringByEvaluatingJavaScriptFromString:message];
        return NO;
    }
    if ([url containsString:@"obj://regist"]) {
       UIAlertController *alert =  [UIAlertController alertControllerWithTitle:@"开始注册" message:@"注册" preferredStyle:UIAlertControllerStyleAlert];
        [alert addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
            
        }]];
        [self presentViewController:alert animated:YES completion:nil];
        return NO;
    }
    return YES;
}
2017-12-21 17_54_52.gif

当点击登录时,我们拦截了登录,然后用该方法直接调取了JS中的方法nativeCall(), 并传递了参数 hello javascript,此时必须注意,传递参数的时候需要用单引号,参数多的,用,隔开即可。

我们也可以将一个字典对象通过反序列化成一个NSString来传递给JS,例如:

JS代码


function introduce (person) {
          var people = JSON.parse(person);
          alert('我是:' + people.name + ',爱好:' + people.like);
}

OC代码

if ([url containsString:@"obj://introduce"]) {
    NSDictionary *dic = @{@"name" : @"leevi", @"like" : @"woman"};
    NSData *dicData = [NSJSONSerialization dataWithJSONObject:dic options:0 error:nil];
    NSString *str = [[NSString alloc] initWithData:dicData encoding:NSUTF8StringEncoding];
    NSString *message = [NSString stringWithFormat:@"introduce('%@')", str];
    [theWebView stringByEvaluatingJavaScriptFromString:message];
    return NO;
}

运行效果如下:


2017-12-22 09_44_09.gif

但这个方法只能传字符串给JS,没法传一个OC的对象,之后我们通过JavaScriptCore 可以实现传一个OC对象。

该方法是有返回值的,我们可以直接在JS的方法中返回给Native参数。
JS

function introduce (person) {
    var people = JSON.parse(person);
    alert('我是:' + people.name + ',爱好:' + people.like);
    return '啦啦';
}  

OC

NSString *jsReturn =  [theWebView stringByEvaluatingJavaScriptFromString:message];
NSLog(@"%@", jsReturn);

打印

15139228701821.jpg

你可能感兴趣的:(JS与原生OC交互通信(一))