用户操作交互
就是截获JS调用alert、confirm、prompt函数,来使用原生控件实现样式及操作,并将用户操作回调给JS
代理:WKUIDelegate
具体步骤:
1、设置代理
webView.UIDelegate = self;
2、完成代理方法
部分代理方法
// 在JS端调用alert函数时,会触发此代理方法。
// JS端调用alert时所传的数据可以通过message拿到
// 在原生得到结果后,需要回调JS,是通过completionHandler回调
-(void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler;
// JS端调用confirm函数时,会触发此方法
// 通过message可以拿到JS端所传的数据
// 在iOS端显示原生alert得到YES/NO后
// 通过completionHandler回调给JS端
-(void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler;
// JS端调用prompt函数时,会触发此方法
// 要求输入一段文本
// 在原生输入得到文本内容后,通过completionHandler回调给JS
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler;
演示:
演示自定义方法
就是截获JS调用自定义方法,实现某些功能
代理:WKScriptMessageHandler
具体步骤:
1、注册方法
[webView.configuration.userContentController addScriptMessageHandler:self name:@"copyWeiXinHao"]; // 复制微信号
[webView.configuration.userContentController addScriptMessageHandler:self name:@"goToWeiXinApp"]; // 跳转微信App
[webView.configuration.userContentController addScriptMessageHandler:self name:@"getCurrentContent"]; // 获取原生剪切板内容
2、实现WKScriptMessageHandler方法、注册的方法
// message.name为方法名
// message.body为js传递的参数,是个id类型
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
if ([message.name isEqualToString:@"copyWeiXinHao"]) {
NSString *wxh = message.body;
NSLog(@"微信号:%@",wxh);
[self copyWeiXinHao:wxh];
}
else if ([message.name isEqualToString:@"getCurrentContent"]) {
NSString *content = [self getCurrentContent];
NSString *promptCode = [NSString stringWithFormat:@"getCurrentWeiXinHao(\"%@\")",content];
// OC传递数据给JS
[self.webView.webView evaluateJavaScript:promptCode completionHandler:^(id _Nullable response, NSError * _Nullable error) {
}];
}
else if ([message.name isEqualToString:@"goToWeiXinApp"]) {
[self goToWeiXinApp];
}
}
// 复制微信号
-(void)copyWeiXinHao:(NSString *)wxh{
[[UIPasteboard generalPasteboard] setString:wxh];
}
// 当前剪切板信息
-(NSString*)getCurrentContent{
return [[UIPasteboard generalPasteboard] string];
}
// 跳转微信应用
-(void)goToWeiXinApp{
NSURL *url = [NSURL URLWithString:@"weixin://"];
BOOL canOpen = [[UIApplication sharedApplication] canOpenURL:url];
if (canOpen){ //打开微信
[[UIApplication sharedApplication] openURL:url];
}else {
NSLog(@"您的设备尚未安装微信");
}
}
3、移除监听
-(void)dealloc{
// 根据name移除
[self.webView.webView.configuration.userContentController removeScriptMessageHandlerForName:@"copyWeiXinHao"];
// [self.webView.webView.configuration.userContentController removeAllUserScripts]; // 移除所有
}
补充:
1、JS传递OC
function 方法名() {
window.webkit.messageHandlers.方法名.postMessage('参数');
}
2、OC传递JS
[webView evaluateJavaScript:@"方法名(参数)" completionHandler:^(id _Nullable response, NSError * _Nullable error) {
}];
演示:
演示补充:JS文件
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, target-densitydpi=device-dpi"/>
<title>JSCallOC</title>
<style>
*
{
//-webkit-tap-highlight-color: rgba(0,0,0,0);
text-decoration: none;
}
html,body
{
-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */
-webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */
-webkit-user-select: none; /* prevent copy paste, to allow, change 'none' to 'text' */
}
#div-a
{
background:#FBA;
color:#FFF;
border-radius: 25px 5px;
}
</style>
</head>
<body style="background:#CDE; color:#FFF">
<div id="div-a">
<center>
<br/>
<input type="button" value=alert onclick="alert('禁止操作');" />
<br/>
<br/>
<input type="button" value="confirm" onclick="confirm('确定提交吗?');" />
<br/>
<br/>
<input type="button" value="prompt" onclick="prompt('请输入姓名');" />
<br/>
<br/>
<input type="button" value="复制微信号" onclick="copyWeiXinHao();" />
<br/>
<br/>
<input type="button" value="跳转微信" onclick="goToWeiXinApp();" />
<br/>
<br/>
<input type="button" value="获取应用剪切板内容" onclick="getCurrentContent();" />
<br/>
<br/>
<a id="push" href="#" onclick="">
xxx
</a>
</center>
</div>
<script type="text/javascript">
function copyWeiXinHao() {
window.webkit.messageHandlers.copyWeiXinHao.postMessage('476512340');
}
function goToWeiXinApp() {
window.webkit.messageHandlers.goToWeiXinApp.postMessage('');
}
function getCurrentContent() {
window.webkit.messageHandlers.getCurrentContent.postMessage('');
}
function getCurrentWeiXinHao(wxh) {
document.getElementById('push').innerText = wxh;
}
</script>
</body>
</html>
⚠️ 坑:
1、WKWebView执行js代码,要先被加载到父视图上
2、关于不能释放问题的解决方案
思路:另外创建一个弱引用代理对象,然后通过代理对象回调指定的self
.h 文件
#import <Foundation/Foundation.h>
#import <WebKit/WebKit.h>
@interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>
@property (nonatomic,weak)id<WKScriptMessageHandler> scriptDelegate;
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;
@end
.m 文件
#import "WeakScriptMessageDelegate.h"
@implementation WeakScriptMessageDelegate
- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate
{
self = [super init];
if (self) {
_scriptDelegate = scriptDelegate;
}
return self;
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
[self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}
@end
使用
1、导入该类
// addScriptMessageHandler 使用新类
[_webView.configuration.userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"xxxx"];
2、依旧removeAllUserScripts
- (void)dealloc{
[self.webView.configuration.userContentController removeAllUserScripts];
}
网友评论