iOS使用WKWebView与H5交互—JS调用原生方法
2018-07-07 本文已影响176人
朝阳小麦
适合人群:iOS开发人员。
内容:iOS中通过UIWebView与H5交互,实现提供原生方法给内嵌H5页面调用。
(UIWebView的交互方式写法与此不同,详见:
https://www.jianshu.com/p/387129b5b350)。
简要:现在iOS开发基本都把UIWebView替换成WKWebView了。于是,项目中之前用的UIWebView与H5交互,也做了更改。本文介绍JS调用OC原生方法。
1.首先呢,写个测试html文件。不会的可以复制下面代码:
<!DOCTYPE html>
<html>
<header>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript">
//首先在JS代码中加入对事先约定好的 ScriptMessage(JS事件)的调用
//window.webkit.messageHandlers.<事件名>.postMessage(需要传递的数据)
//注意:目前测试来看,postMessage(3)必须要传参数,没有的话就放个占位参数,否则OC收不到响应。
function changeOrientation() {
window.webkit.messageHandlers.changeOrientation.postMessage("1");
}
function selectBrowse() {
window.webkit.messageHandlers.selectBrowse.postMessage("6");
}
function saveFloorId() {
window.webkit.messageHandlers.saveFloorId.postMessage("1234321");
}
</script>
<style>
button {
width:500px;
height:100px;
font-size:30px;
}
</style>
</header>
<body>
<br/>
<br/>
<button type="button" onclick="changeOrientation()">changeOrientation</button>
<br/>
<br/>
<button type="button" onclick="selectBrowse()">selectBrowse</button>
<br/>
<br/>
<button type="button" onclick="saveFloorId()">saveFloorId</button>
</body>
</html>
2.接下来就是OC部分了。创建一个控制器界面,用于显示H5页面。先上代码吧,代码不多,也都有注释。
ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
ViewController.m
#import "ViewController.h"
#import <WebKit/WebKit.h>//用WKWebView需要导入
@interface ViewController ()<WKNavigationDelegate, WKScriptMessageHandler>
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.webView];
self.webView.frame = self.view.bounds;
NSString *weburl = [[NSBundle mainBundle] pathForResource:@"color"ofType:@"html"];
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:weburl]]];
}
#pragma mark - WKScriptMessageHandler协议方法
// - (void)changeOrientation:(NSInteger)param;
// - (void)selectBrowse;
// - (void)saveFloorId:(NSString *)floorId;
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"JS 调用了 %@ 方法,传回参数 %@",message.name,message.body);
if ([message.name isEqualToString:@"changeOrientation"]) {
NSInteger body = [message.body integerValue];
[self changeOrientation:body];
}
else if ([message.name isEqualToString:@"selectBrowse"]) {
[self selectBrowse];
}
else if ([message.name isEqualToString:@"saveFloorId"]) {
[self saveFloorId:message.body];
}
}
#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation {
}
#pragma mark - methods.
- (void)changeOrientation:(NSInteger)param {
NSLog(@"changeOrientation---%ld", (long)param);
}
- (void)selectBrowse {
NSLog(@"selectBrowse---");
}
- (void)saveFloorId:(NSString *)floorId {
NSLog(@"saveFloorId---%@", floorId);
}
#pragma mark - lazy load.
- (WKWebView *)webView {
if (!_webView) {
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.preferences.javaScriptEnabled = YES;
config.userContentController = [[WKUserContentController alloc] init];
[config.userContentController addScriptMessageHandler:self name:@"changeOrientation"];
[config.userContentController addScriptMessageHandler:self name:@"selectBrowse"];
[config.userContentController addScriptMessageHandler:self name:@"saveFloorId"];
WKPreferences *preferences = [WKPreferences new];
preferences.javaScriptCanOpenWindowsAutomatically = YES;
config.preferences = preferences;
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
_webView.navigationDelegate = self;
}
return _webView;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
3.就这么多代码。现在简单概括两点:
(1)WKWebView的初始化:
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
config.userContentController = [[WKUserContentController alloc] init];
//注册WKScriptMessageHandler协议代理
[config.userContentController addScriptMessageHandler:self name:@"changeOrientation"];
[config.userContentController addScriptMessageHandler:self name:@"selectBrowse"];
[config.userContentController addScriptMessageHandler:self name:@"saveFloorId"];
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];
_webView.navigationDelegate = self;
(2)实现WKScriptMessageHandler协议方法:
#pragma mark - WKScriptMessageHandler协议方法
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
NSLog(@"JS 调用了 %@ 方法,传回参数 %@",message.name,message.body);
if ([message.name isEqualToString:@"changeOrientation"]) {
NSInteger body = [message.body integerValue];
[self changeOrientation:body];
}
else if ([message.name isEqualToString:@"selectBrowse"]) {
[self selectBrowse];
}
else if ([message.name isEqualToString:@"saveFloorId"]) {
[self saveFloorId:message.body];
}
}
完成。
写法上比UIWebView简单方便多了。
4.关于WKScriptMessageHandler协议代理是否需要注销问题,目前不确定是否会影响到内存泄漏。
//销毁代理
[_webView.configuration.userContentController removeScriptMessageHandlerForName:@"changeOrientation"];
[_webView.configuration.userContentController removeScriptMessageHandlerForName:@"selectBrowse"];
[_webView.configuration.userContentController removeScriptMessageHandlerForName:@"saveFloorId"];
这个疑问有答案了再解决吧。目前观察看,没发现严重内存泄漏。