iOS与JS交互的方法:

1.拦截url(适用于UIWebView和WKWebView)
2.JavaScriptCore(只适用于UIWebView,iOS7+)
3.WKScriptMessageHandler(只适用于WKWebView,iOS8+)
4.WebViewJavascriptBridge(适用于UIWebView和WKWebView,属于第三方框架)

下面以假设的需求进行示例代码讲解,需求:
(1)h5页面调用原生扫二维码(h5调用原生)
(2)原生扫码成功后,将结果返回给h5(原生调用h5)

方法一. 拦截url

(1)web调用原生:

<1>和后端同事协定好协议,如jxaction://scan表示启动二维码扫描,jxaction://location表示获取定位。
<2>实现UIWebView代理的shouldStartLoadWithRequest:navigationType:方法,在方法中对url进行拦截,如果是步奏<1>中定义好的协议则执行对应原生代码,返回false,否则返回true继续加载原url。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{if ([request.URL.absoluteString hasPrefix:@"jxaction://scan"]) {//调用原生扫描二维码return NO;}return YES;
}

h5代码:

<a href="jxaction://scan">扫一扫(拦截url)</a>

(2)原生调用js

若(1)中扫描二维码结束后,需要把扫描结果返回给web页,直接调用UIWebView的stringByEvaluatingJavaScriptFromString:方法,或者WKWebView的 evaluateJavaScript:completionHandler:方法。

[self.webView stringByEvaluatingJavaScriptFromString:@"scanResult('我是扫描结果~')"];

方法二. JavaScriptCore

方法一web调用原生只适合简单的调用,如果要传递参数,虽然也可以拼接在url上,如jxaction://scan?method=aaa,但是需要我们自行对字符串进行分割解析,并且特殊字符需要编码。在iOS7系统提供了JavaScriptCore,可以更优雅地实现js与原生的交互。
(1)js调用原生
<1>新建类继承自NSObject(如AppJSObject)。
<2>.h文件中声明一个代理并遵循JSExport,代理内的方法和js定义的方法名一致。
<3>.m文件中实现<2>代理中对应的方法,可以在方法内处理事件或通知代理。

AppJSObject.h

\#import <Foundation/Foundation.h>
\#import <JavaScriptCore/JavaScriptCore.h>@protocol AppJSObjectDelegate <JSExport>-(void)scan:(NSString *)message;@end@interface AppJSObject : NSObject<AppJSObjectDelegate>@property(nonatomic,weak) id<AppJSObjectDelegate> delegate;@end

AppJSObject.m

#import "AppJSObject.h"@implementation AppJSObject-(void)scan:(NSString *)message{[self.delegate scan:message];
}@end

h5代码:

<input type="button" name="" value="扫一扫" onclick="scan()">
<br/>
<p id="result">扫描结果:</p><script type="text/javascript">//调用APP的扫描方法   h5->appfunction scan(){app.scan('scanResult');}//扫描结果回调方法    app->h5function scanResult(result){document.getElementById("result").innerHTML = '扫描结果:' + result;  }
</script>

<4>在UIWebView加载完成的代理中把AppJSObject实例对象类注入到JS中,那么在js中调用方法就会调用到原生AppJSObject实例对象中对应的方法了。

-(void)webViewDidFinishLoad:(UIWebView *)webView
{JSContext *context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];AppJSObject *jsObject = [AppJSObject new];jsObject.delegate = self;context[@"app"] = jsObject;}

代码:https://github.com/dolacmeng/JSDemo/tree/master
*也可以通过block实现而不创建新类AppJSObject:

context[@"openAlbum"] = ^(){NSLog(@"js调用oc打开相册");
};

(2)原生调用js

可以通过一中的方法,也可以通过JSContext:

JSContext *context=[_mainWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
NSString *alertJS= [NSString stringWithFormat:@"%@('%@')",_photoMethod,fileUrl];
[context evaluateScript:alertJS];

方法三. WKScriptMessageHandler

现在很多app都是支持iOS8+,很多人使用WKWebView代替了UIWebView,但是WKWebView并不支持方法二。此时我们可以使用WKWebView的WKScriptMessageHandler
<1>初始化WKWebView时,调用addScriptMessageHandler:name:方法,name为js中的方法名,如scan:

- (void)setupWKWebView{WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];configuration.userContentController = [[WKUserContentController alloc] init];[configuration.userContentController addScriptMessageHandler:self name:@"scan"];WKWebView *webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];webView.UIDelegate = self;
}

h5:

window.webkit.messageHandlers.scan.postMessage() 

<2>实现WKScriptMessageHandler代理方法,当js调用scan方法时,会回调此代理方法:


- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{if ([message.name isEqualToString:@"scan"]) {//调用原生扫码}
}

方法四 WebViewJavascriptBridge

是一个第三方框架,官方文档和demo都很完整,不再累赘,GitHub地址:
https://github.com/marcuswestin/WebViewJavascriptBridge

iOS与JS交互的4种方法相关推荐

  1. iOS: JS和Native交互的两种方法,iosjsnative交互

    iOS: JS和Native交互的两种方法,iosjsnative交互 背景: UIWebView: iOS 用来展示 web 端内容的控件. 1. 核心方法: - (NSString*)string ...

  2. js修改style中某个属性_JS 和 CSS 交互的 5 种方法

    英文 | https://davidwalsh.name/ways-css-javascript-interact译文 | https://www.webhek.com/post/ways-css-j ...

  3. 动态加载JS脚本的4种方法

    动态加载JS脚本的4种方法 2006-12-04 15:33 要实现动态加载JS脚本有4种方法: 1.直接document.write <script language="javasc ...

  4. python制作系统程序与html交互_python+html语音人物交互_flask后台与前端(html)交互的两种方法...

    基于python flask框架搭建web flask后台与前端(html)交互的两种方法: 方法1 使用flask-wtf 提供的表单 用常见的登录为例: // An highlighted blo ...

  5. 实现和IE浏览器交互的几种方法

    实现和IE浏览器交互的几种方法       浙江大学计算机系   (310027)       胡朝晖   陈奇   俞瑞钊          如何实现对IE浏览器中对象的操作是一个很有实际意义的问题 ...

  6. node.js取参四种方法req.body,req.params,req.param,req.body

    node.js取参四种方法req.body,req.params,req.param,req.body 参考:https://my.oschina.net/u/2519530/blog/535309 ...

  7. js延迟加载的几种方法

    这是一个面试经常问到的问题:js的延迟加载方法 (js的延迟加载有助与提高页面的加载速度) 主要考察对程序的性能方面是否有研究,程序的性能是一个项目不断地追求的,通常也是项目完成后需要长期做的一件事情 ...

  8. 实现动态加载JS脚本有4种方法

    转自:微点阅读  https://www.weidianyuedu.com 实现动态加载JS脚本有4种方法: 1.直接document.write 这里重新温习Document.write()的用法, ...

  9. iOS WKWebView和JS交互的两种方式

    2019独角兽企业重金招聘Python工程师标准>>> 本文介绍两种方式实现iOS WKWebView和JS交互 WKWebViewConfiguration注入WKScriptMe ...

最新文章

  1. C技巧:结构体参数转成不定参数
  2. 无需成对示例、无监督训练,CycleGAN生成图像简直不要太简单
  3. 三十六、请求分页管理方式
  4. PowerDesigner逆向工程mysql
  5. mysql存储过程 php_PHP调用MYSQL存储过程实例
  6. 双向控制引脚的控制代码
  7. 在POM 4中,dependency中还引入了scope可以使用5个值
  8. mysql用命令修改主键名_MySQL的常用命令:添加外键,修改字段名称,增加字段 设置主键自增长等...
  9. 信息学奥赛一本通(1095:数1的个数)
  10. iPhone入门教程 (视频)
  11. 解题报告: LeetCode Max Points on a Line
  12. Vue源码学习目录(持续更新中)
  13. 【美女送福利了win7主题】
  14. 2021年下半年软件设计师下午真题试题(案例分析)及答案
  15. java 网易邮箱_Java mail 163邮箱配置
  16. 计算机二级考试真题李阳答案,英语二级笔译_二级笔译培训_二级笔译真题 - 沪江英语...
  17. 代码设置margintop_js获取css属性,更改margin-top属性,给每个a标签的margin-top属性在原基础上 +5px...
  18. nginx -s reopen的理解
  19. opencv-python的颜色检测追踪
  20. 下班后10条最佳放松方法

热门文章

  1. HtmlUnit、httpclient、jsoup爬取网页信息并解析
  2. SSL 1460——最小代价问题
  3. Cacti安装详细步骤
  4. 整理收集49条JQuery代码小结
  5. Facebook如何使用Avartarnode提升HDFS可靠性
  6. Varnish purges 缓存清除
  7. 安装varish作为缓存和代理
  8. 在C#中使用代理的方式触发事件
  9. 内存性能参数详解(转载)
  10. Linux进程浏览器htop安装与使用