iOS JS 和 OC交互 / JS 和 native 相互调用

现在app 上越来越多需求是通过UIWebView 来展示html 或者 html5的内容, js 和 native OC代码交互 就非常常见了.

js 调用 native  OC代码

第一种机制

(1)最常用的是 利用 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType 这个UIWebView 代理方法里拦截 JS 发送的请求,如果是约定的请求 那么就触发本地该执行的OC方法

我遇到常用的两种场景:

(1.1)页面缓冲加载过程中 该shouldStartLoadWithRequest:就可拦截多个请求,查找约定的关键字,锁定约定请求即可触发本地OC

(1.2)页面有按钮类别的焦点区域, 点击触发请求,通过 shouldStartLoadWithRequest: 对请求进行判断 ,触发本地OC

     举例:html 分享按钮

<html>
    <header>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript">function shareClick() {
                loadURL("iOS//:shareAction");//这个链接对应 下面iOS方法中同一链接的关键字
            }
        </script>
    </header>

    <body>
        <h2> 点击webView上面的按钮 触发本地 OC 分享方法 </h2>
        <button type="button" onclick="shareClick()">按钮名称</button>
    </body>
</html>

 

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *requestUrl = request.URL.absoluteString;
DLog(@"请求URL:%@",requestUrl);
//判断是商品
if(![NSString isEmpty:requestUrl] && [requestUrl hasPrefix:@"hfmall://"]) {//约定 按请求前缀 是"hfmall://"来判断是商品 甚至可以从请求链接里面截取有效参数 如果频繁处理并且几个参数或者说有特殊字符,应该考虑用json进行64位编拼在链接上传过来 NSRange range = [requestUrl rangeOfString:@"hfmall://"]; if (range.length > 0) { NSString *shangpinId = [requestUrl substringFromIndex:range.length]; GoodsDetailViewController *detailVC = [[GoodsDetailViewController alloc] init]; detailVC.shangpin_id = shangpinId; [self.navigationController pushViewController:detailVC animated:YES]; return NO; //执行本地代码 返回NO } }
//点击UIWebView页面上分享按钮 执行本地OC 分享方法
//是文章分享
   NSRange range1 = [requestUrl rangeOfString:@"ios//:shareAction"];
if (range1.length != 0) {
[self share]; //执行分享方法
return NO;
}
//TODO:其他情况拦截判断
return YES;//无有效需要拦截的链接 走系统默认方法
}

 

第二种机制

JavaScripCore

该框架 在 iOS7开始出现,可以实现 js 和 native OC原生交互,添加头文件#import <JavaScriptCore/JavaScriptCore.h>

 

[webView loadRequest:request];请求开始或者请求完成后获取js上下文

(1)js 自由选择时机调用native端 OC 代码

html端

<html>
    <header>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript">
            function secondClick() {
                iosHideBottomBar('参数1','参数2');//和 OC代码中标记红色背景关键名称一样 即可识别
            }
</script> </header> <body> <h2> js 自由选择时机调用native端 OC 代码 </h2> <button type="button" onclick="secondClick()">按钮名称</button> </body> </html>

 

//获取js上下文
JSContext
*context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

  context[@"iosHideBottomBar"] = ^() { // @"iosHideBottomBar"为和js 约定执行的方法名,这样js 可以自由选择时机调用native端 OC 代码

        DLog(@"%@",[NSThread currentThread]);//打印当前线程

     NSArray *args = [JSContext currentArguments];//回调js 方法iosHideBottomBar传递的参数

        for (JSValue *jsVal in args) {

            DLog(@"%@", jsVal.toString);

        }

        __block JSContext *contextObject = context;

       dispatch_async(dispatch_get_main_queue(), ^{

            self.isShowLikeFooter = NO;

            [self handleHiddenBottomBar];

            NSString *jsString=@"xxxxx('如果需要传递返回值')"; //准备执行的js代码 按约定方法xxxxx回传返回值

            [contextObject evaluateScript:jsString];

        });

  };

 //该闭包是在非主线程中得到的回调,如果需要处理UI要在主线程更新 当前测试环境 为 XCode 8.0 模拟器 5s 8.3 打印结果如下

/**
2016-11-11 17:05:54.447 dailylife[4163:181210] <NSThread: 0x7ff68cc2fd90>{number = 7, name = (null)}

(lldb) po [NSThread currentThread]

<NSThread: 0x7ff68a423150>{number = 1, name = main}

**/

 小节:

两种机制不同:

a.  前者需要 不断对js 发起的每一条请求进行过滤判断,再执行早已定义好的OC方法,因为无法预知具体需要触发本地OC方法时机,

b.  后者 js 和 OC约定同一个方法名做识别关键字iosHideBottomBar 年 在JSContext获取webView js上下文,告诉js 本地有这个同样方法名的OC方法,你可以随时调用(子线程中).

体验下来,发现 后者这种 webView 控制调用更合理,在需要的时候调用.  但是现在好多第三方 用的都是前者,拦截url判断的方法,比如"有赞"就是,所以两种方法 我们都应该掌握,在需要的的时候选择相对更优的方式处理实现

native OC 调用 js

调用时机是应该是 webFinishLoad后, 

(1)stringByEvaluatingJavaScriptFromString : 我常用这个方法去获取 webView标题

NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];

@"document.title" 传递给js  (js call native) 是异步的

当js 返回的 title字符串 (native call  js) 是同步得到的

stringByEvaluatingJavaScriptFromString 方法应该在主线程中执行,

这个方法也可以oc js相互传递参数 

这个方法调用时机:应该在webview 请求完成后再调用 js 方法,这里才能用stringByEvaluatingJavaScriptFromString,因为

要等页面加载完,页面没加载完就相当于有些对象不一定创建成功,那么用js时候就容易找不到对象

(2)

//创建对象 context 获取 js上下文
JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];      \
NSString
*jsString=@"iosHideBottomBar('参数1','参数2')"; //准备执行的js代码 并向iOS 传递参数1 参数2 [context evaluateScript:jsString];//通过oc方法调用js的 iosHideBottomBar

 

其他情况:

我还特意考虑了 相互需要返回值的可能

在具体上面方法举例,使用方法名时候 有特意强调参数,和返回值的情况不再赘述

参考:

http://blog.devtang.com/2012/03/24/talk-about-uiwebview-and-phonegap/

http://www.jianshu.com/p/d19689e0ed83

 

转载于:https://www.cnblogs.com/someonelikeyou/p/6054547.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Web开发中,JSNative交互是指通过JavaScriptJS)代码和本地代码进行相互通信的过程。JS是一种脚本语言,在浏览器中执行,而Native是指底层本地代码,如Android的Java或iOS的Objective-C/Swift。 JSNative交互的目的是为了在Web应用程序中获得更强大的功能和更好的用户体验。通过JSNative交互,可以实现以下功能: 1. 调用Native功能:JS可以通过与Native进行通信,调用本地功能,例如访问设备的传感器、获取设备信息、发送本地推送等。这样,Web应用程序就可以更好地与设备硬件和本地特性进行交互。 2. 获取Native数据:JS可以向Native请求数据,例如获取本地数据库的数据、获取设备的位置信息等。通过这种方式,Web应用程序可以使用本地的数据,实现更为复杂和个性化的功能。 3. 更新Web页面:Native可以通过调用JS的代码来更新Web页面的内容,例如在Native端接收到新的数据时,可以通过JS将数据更新到Web页面上,实现实时的页面刷新。 为了实现JSNative交互,通常有以下几种方式: 1. 使用WebView提供的接口:在移动应用中,使用WebView作为嵌入式浏览器可以实现JSNative交互。通过WebView提供的接口,可以在JSNative之间进行消息传递和函数调用。 2. 使用JavaScriptBridge:JavaScriptBridge是一种将JSNative进行桥接的技术。通过在Native代码中注入JavaScriptBridge对象,并在JS代码中引用相关的Native方法和属性,可以实现JSNative相互调用。 3. 使用消息机制:在一些特定的平台上,还可以通过消息机制实现JSNative之间的通信。例如,Android平台可以使用JavaScriptInterface来定义JS可以调用Native方法,而iOS平台可以使用WKWebView提供的消息机制进行JSNative交互。 总结来说,JSNative交互是为了实现Web应用程序与本地功能和数据的交互,通过使用WebView接口、JavaScriptBridge或消息机制,可以实现JSNative相互调用和通信。这样一来,Web应用程序就能获得更多的功能和更好的用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值