本文介绍的是WKWebView与JS之前的互调
- WKWebView的基本设置,如下:
@interface ViewController : UIViewController <WKScriptMessageHandler,WKUIDelegate>
@end
@interface ViewController ()
@property (nonatomic,strong) WKWebView *wkWebView;
@end
- (void)viewDidLoad {
[super viewDidLoad];
self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];
// JS的alert、confirm的提示,APP需要处理下
self.wkWebView.UIDelegate = self;
// 载入JS页面
[self.wkWebView loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.5.148:8088/test.html"]]];
[self.view addSubview:self.wkWebView];
}
- JS的alert、confirm在APP上进行提示
# pragma WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
[self showAlert:message isConfirm:NO];
completionHandler();// 注意completionHandler,必须调,否则会崩
}
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
[self showAlert:message isConfirm:YES];
completionHandler(NO);// 注意completionHandler,必须调,否则会崩
}
- (void)showAlert:(NSString *)str isConfirm:(BOOL)isConfirm{
NSString *msg = [NSString stringWithFormat:@"\n %@",str];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:ok];
// 是否显示取消按钮
if (isConfirm) {
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:cancel];
}
[self presentViewController:alert animated:YES completion:nil];
}
3.1. APP调用JS方法
// 在APP内viewDidLoad里搞两个APP原生按钮,如下
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"callJs1" style:UIBarButtonItemStyleDone target:self action:@selector(callJs1)];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"callJs2" style:UIBarButtonItemStyleDone target:self action:@selector(callJs2)];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:item1,item2, nil];
- (void)callJs1 {
[self.wkWebView evaluateJavaScript:@"showmsg1('我是来自app的消息')" completionHandler:^(id _Nullable item, NSError * _Nullable err) {
NSLog(@"item=%@,err=%@",item,err);
}];
}
// JS方法如下
<script>
function showmsg1(str) {
alert(str)
}
</script>
3.2. 另外,APP也可以把自定义的JS方法,注入到JS内,如下
// 把APP自定义的JS方法,注入到JS内
NSString *jsString = @"function appAlert(str) { alert(str);} ";
WKUserScript *script = [[WKUserScript alloc] initWithSource:jsString injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[ucc addUserScript:script];
// APP调用注入的JS方法
- (void)callJs2 {
[self.wkWebView evaluateJavaScript:@"appAlert('我是来自app注入方法的消息')" completionHandler:^(id _Nullable item, NSError * _Nullable err) {
NSLog(@"item=%@,err=%@",item,err);
}];
}
// JS也可以调用APP自定义的JS方法
<script>
function showmsg2(str) {
appAlert(str)
}
</script>
- JS调用APP方法
// JS方法如下
<script>
function call_app_method_1() {
window.webkit.messageHandlers.app_method_1.postMessage(null)
}
function call_app_method_2() {
window.webkit.messageHandlers.app_method_2.postMessage(['a', 'b', 'c'])
}
</script>
// 把APP的方法添加到JS内
WKUserContentController *ucc = self.wkWebView.configuration.userContentController;
[ucc addScriptMessageHandler:self name:@"app_method_1"];
[ucc addScriptMessageHandler:self name:@"app_method_2"];
// JS调用APP添加到JS的方法,由下面的方法进行区分
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"message.name = %@",message.name); // APP方法名
NSLog(@"message.body = %@",message.body); // JS的入的参数
}
- 注意内存回收处理
- (void)dealloc {
[self.wkWebView.configuration.userContentController removeAllUserScripts];
}
JS完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>tit</title>
</head>
<body>
<input type="button" value="alert1" onclick="showmsg1('我是来自JS的消息1')" />
<input type="button" value="alert2" onclick="showmsg2('我是来自JS的消息2')" />
<input type="button" value="alert3" onclick="showmsg3('我是来自JS的消息3')" />
<input type="button" value="call_app_method_1" onclick="call_app_method_1()" />
<input type="button" value="call_app_method_2" onclick="call_app_method_2()" />
</body>
<script>
function showmsg1(str) {
alert(str)
}
function showmsg2(str) {
appAlert(str)
}
function showmsg3(str) {
confirm(str)
}
function call_app_method_1() {
window.webkit.messageHandlers.app_method_1.postMessage(null)
}
function call_app_method_2() {
window.webkit.messageHandlers.app_method_2.postMessage(['a', 'b', 'c'])
}
</script>
</html>
APP完整代码:
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@interface ViewController : UIViewController <WKScriptMessageHandler,WKUIDelegate>
@end
@interface ViewController ()
@property (nonatomic,strong) WKWebView *wkWebView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// APP原生的两个按钮
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"callJs1" style:UIBarButtonItemStyleDone target:self action:@selector(callJs1)];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"callJs2" style:UIBarButtonItemStyleDone target:self action:@selector(callJs2)];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:item1,item2, nil];
// WKWebView基本设置
self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];
// JS的alert、confirm的提示,APP需要处理下
self.wkWebView.UIDelegate = self;
// 载入JS页面
[self.wkWebView loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.0.103:8088/test.html"]]];
[self.view addSubview:self.wkWebView];
// 把APP的方法添加到JS内
WKUserContentController *ucc = self.wkWebView.configuration.userContentController;
[ucc addScriptMessageHandler:self name:@"app_method_1"];
[ucc addScriptMessageHandler:self name:@"app_method_2"];
// 把APP自定义的JS方法,注入到JS内
NSString *jsString = @"function appAlert(str) { alert(str);} ";
WKUserScript *script = [[WKUserScript alloc] initWithSource:jsString injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[ucc addUserScript:script];
}
- (void)callJs1 {
[self.wkWebView evaluateJavaScript:@"showmsg1('我是来自app的消息')" completionHandler:^(id _Nullable item, NSError * _Nullable err) {
NSLog(@"item=%@,err=%@",item,err);
}];
}
- (void)callJs2 {
[self.wkWebView evaluateJavaScript:@"appAlert('我是来自app注入方法的消息')" completionHandler:^(id _Nullable item, NSError * _Nullable err) {
NSLog(@"item=%@,err=%@",item,err);
}];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"message.name = %@",message.name);
NSLog(@"message.body = %@",message.body);
}
# pragma WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
[self showAlert:message isConfirm:NO];
completionHandler();// 注意completionHandler,必须调,否则会崩
}
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
[self showAlert:message isConfirm:YES];
completionHandler(NO);// 注意completionHandler,必须调,否则会崩
}
// 注意内存回收处理
- (void)dealloc {
[self.wkWebView.configuration.userContentController removeAllUserScripts];
}
- (void)showAlert:(NSString *)str isConfirm:(BOOL)isConfirm{
NSString *msg = [NSString stringWithFormat:@"\n %@",str];
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:ok];
// 是否显示取消按钮
if (isConfirm) {
UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:cancel];
}
[self presentViewController:alert animated:YES completion:nil];
}
@end