iOS与JS交互的4种方法
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种方法相关推荐
- iOS: JS和Native交互的两种方法,iosjsnative交互
iOS: JS和Native交互的两种方法,iosjsnative交互 背景: UIWebView: iOS 用来展示 web 端内容的控件. 1. 核心方法: - (NSString*)string ...
- js修改style中某个属性_JS 和 CSS 交互的 5 种方法
英文 | https://davidwalsh.name/ways-css-javascript-interact译文 | https://www.webhek.com/post/ways-css-j ...
- 动态加载JS脚本的4种方法
动态加载JS脚本的4种方法 2006-12-04 15:33 要实现动态加载JS脚本有4种方法: 1.直接document.write <script language="javasc ...
- python制作系统程序与html交互_python+html语音人物交互_flask后台与前端(html)交互的两种方法...
基于python flask框架搭建web flask后台与前端(html)交互的两种方法: 方法1 使用flask-wtf 提供的表单 用常见的登录为例: // An highlighted blo ...
- 实现和IE浏览器交互的几种方法
实现和IE浏览器交互的几种方法 浙江大学计算机系 (310027) 胡朝晖 陈奇 俞瑞钊 如何实现对IE浏览器中对象的操作是一个很有实际意义的问题 ...
- 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 ...
- js延迟加载的几种方法
这是一个面试经常问到的问题:js的延迟加载方法 (js的延迟加载有助与提高页面的加载速度) 主要考察对程序的性能方面是否有研究,程序的性能是一个项目不断地追求的,通常也是项目完成后需要长期做的一件事情 ...
- 实现动态加载JS脚本有4种方法
转自:微点阅读 https://www.weidianyuedu.com 实现动态加载JS脚本有4种方法: 1.直接document.write 这里重新温习Document.write()的用法, ...
- iOS WKWebView和JS交互的两种方式
2019独角兽企业重金招聘Python工程师标准>>> 本文介绍两种方式实现iOS WKWebView和JS交互 WKWebViewConfiguration注入WKScriptMe ...
最新文章
- C技巧:结构体参数转成不定参数
- 无需成对示例、无监督训练,CycleGAN生成图像简直不要太简单
- 三十六、请求分页管理方式
- PowerDesigner逆向工程mysql
- mysql存储过程 php_PHP调用MYSQL存储过程实例
- 双向控制引脚的控制代码
- 在POM 4中,dependency中还引入了scope可以使用5个值
- mysql用命令修改主键名_MySQL的常用命令:添加外键,修改字段名称,增加字段 设置主键自增长等...
- 信息学奥赛一本通(1095:数1的个数)
- iPhone入门教程 (视频)
- 解题报告: LeetCode Max Points on a Line
- Vue源码学习目录(持续更新中)
- 【美女送福利了win7主题】
- 2021年下半年软件设计师下午真题试题(案例分析)及答案
- java 网易邮箱_Java mail 163邮箱配置
- 计算机二级考试真题李阳答案,英语二级笔译_二级笔译培训_二级笔译真题 - 沪江英语...
- 代码设置margintop_js获取css属性,更改margin-top属性,给每个a标签的margin-top属性在原基础上 +5px...
- nginx -s reopen的理解
- opencv-python的颜色检测追踪
- 下班后10条最佳放松方法