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

时间:2022-09-23 10:57:31

现在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 > ) {
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

iOS JS 和 OC交互 / JS 和 native 相互调用的更多相关文章

  1. 转载 【iOS开发】网页JS与OC交互(JavaScriptCore) OC -----&gt&semi;JS

      目标 本文介绍利用苹果在iOS7时发布的JavaScriptCore.framework框架进行js与OC的交互.我们想要达到的目标是: OC调用网页上的js方法 网页js调用APP中的OC方法 ...

  2. 史上最全的 UIWebview 的 JS 与 OC 交互

    来源:伯乐在线 - 键盘风筝 链接:http://ios.jobbole.com/89330/ 点击 → 申请加入伯乐在线专栏作者 其实一直想给大家整理一下JS与OC的交互,但是没有合适的机会,今天借 ...

  3. MXBridge - 插件式JS与OC交互框架

    概述 MXBridge,提供一个插件式的JavaScript与Objective-C交互的框架,通过JavaScriptCore实现,插件式扩展Obejctive-C接口以供JavaScript调用. ...

  4. JS与OC交互--简单使用

    直接上代码 .m文件 #import "ViewController.h" @interface ViewController () <UIWebViewDelegate&g ...

  5. Android JNI学习&lpar;三&rpar;——Java与Native相互调用

    本系列文章如下: Android JNI(一)——NDK与JNI基础 Android JNI学习(二)——实战JNI之“hello world” Android JNI学习(三)——Java与Nati ...

  6. UIWebView中JS与OC交互 WebViewJavascriptBridge的使用

    一.综述 现在很多的应用都会在多种平台上发布,所以很多程序猿们都开始使用Hybrid App的设计模式.就是在app上嵌入网页,只要写一份网页代码,就可以跑在不同的系统上.在iOS中,app多是通过W ...

  7. JS 与 OC 交互

    WebView与JS的几种交互 IOS中 使用JavaScriptCore 实现OC与JS的交互 JavaScriptCore 使用

  8. 利用WKWebView实现js与OC交互注意事项

    最近在写一些关于wkwebview的一些代码,发现了几点心得,记录一下. 1.js调用OC 我是利用wkwebview进行的开发实现,主要代码有三部分 1.向config注入OC对象 [config. ...

  9. JS与OC交互,JS中调用OC方法&lpar;获取JSContext的方式&rpar;

    最近用到JS和OC原生方法调用的问题,查了许多资料都语焉不详,自己记录一下吧,如果有误欢迎联系我指出. JS中调用OC方法有三种方式: 1.通过获取JSContext的方式直接调用OC方法 2.通过继 ...

随机推荐

  1. javax&period;el&period;PropertyNotFoundException&colon;

    javax.el.PropertyNotFoundException: Property 'ContextPath' not found on type org.apache.catalina.cor ...

  2. JQ中 trigger&lpar;&rpar;和triggerHandler&lpar;&rpar;区别

    既然使用了trigger和triggerHandler,那么你应该了解了他们的差别了. trigger():在每一个匹配的元素上触发某类事件. triggerHandler():这个特别的方法将会触发 ...

  3. jQuery实现表单验证

    表单是网页的一个重要组成部分.本节做一个简单的表单提交网页然后利用jQuery实现表单的验证.后续的表单完善以及功能的完善会在以后的博客中给出. 效果图: 代码: <!DOCTYPE html ...

  4. &lt&semi;转&gt&semi;一个最不可思议的MySQL死锁分析

    1 死锁问题背景 1 1.1 一个不可思议的死锁 1 1.1.1 初步分析 3 1.2 如何阅读死锁日志 3 2 死锁原因深入剖析 4 2.1 Delete操作的加锁逻辑 4 2.2 死锁预防策略 5 ...

  5. 201521123045 《Java程序设计》第9周学习总结

    201521123045 <Java程序设计>第9周学习总结 1. 本章学习总结 2. 书面作业 本次PTA作业题集异常 1.常用异常题目5-11.1 截图你的提交结果(出现学号) 1.2 ...

  6. cf1061E Politics &lpar;费用流&rpar;

    看到数据范围,考虑网络流..但考的时候完全不知道怎么建图 考虑流量表示选的点个数,费用表示选点的收益,跑最大费用最大流 那么我用一个点x表示某树中的询问点x,刨去它子孙询问点的子树后的子树 对于树1, ...

  7. 原生js--cookie操作的封装

    封装cookie的操作:查询cookie个数.查询所有cookie的键.获取cookie.设置cookie.删除cookie.清除全部cookie /** * cookieStorage */func ...

  8. 使用 grep 的 -o 和 -E 选项进行正则的精确匹配

    sed 命令可以很好的进行行匹配,但从某一行中精确匹配某些内容,则使用 grep 命令并辅以 -o 和 -E 选项可达到此目的.其中 -o 表示“only-matching”,即“仅匹配”之意.光用它 ...

  9. Mediator模式

    [Mediator模式] 通过mediator来让各个相互通知的对象解耦.在iOS框架中就是NSNotificationCenter. 参考:http://www.jdon.com/designpat ...

  10. 前端安全之XSS和csrf攻击

    1.Csrf攻击概念: csrf攻击(Cross-site request forgery):跨站请求伪造; 2.Csrf攻击原理: 用户是网站A的注册用户,且登录进去,于是网站A就给用户下发cook ...