WKWebView
中 JS 和 OC 的交互主要用到 WKUserContentController
WKUserScript
这个类,关于 WKUserContentController
api的讲解请看
WKWebView API详解 这篇文章
注入JS 代码
// JS代码
NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
// 生成 UScript
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
// 生成 UController
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
// 添加 JS
[wkUController addUserScript:wkUScript];
// 配置
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.userContentController = wkUController;
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:wkWebConfig];
执行 JS 代码,获得 webView 的高度
// 加载 js 下面的 js 代码获取高度,但是这种方法获取的高度可能不准确,因为有图片或者视频没有加载出来的情况,内容会有被遮住一部分的情况。
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
// 1.document.documentElement.offsetHeight
// 2.document.body.clientHeight
// 3.document.documentElement.scrollHeight
webView.evaluateJavaScript("document.body.clientHeight") { (result, error) in
if error != nil { return }
let height = result as! CGFloat
}
}
JS 调用 OC 代码(JS 向 OC 发消息)
// 生成 UController
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
// 添加一个 webShare方法供给 JS 调用
[wkUController addScriptMessageHandler:self name:@"webShare"];
JS 调用添加的 webShare
方法
function postMessage(){
var message = {'title':'title','url':'www.baidu.com'}
window.webkit.messageHandlers.webShare.postMessage({body: message});
}
JS 发送过来的数据
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
NSLog(@"js oc name:%@ body:%@",message.name,message.body);
}
完整的代码:
#import "ViewController.h"
@import WebKit;
@interface ViewController ()<WKNavigationDelegate,WKScriptMessageHandler>
@property (nonatomic, strong) WKWebView *webView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self.view addSubview:self.webView];
}
- (WKWebView *)webView
{
if (_webView == nil) {
// JS代码
NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";
// 生成 UScript
WKUserScript *wkUScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
// 生成 UController
WKUserContentController *wkUController = [[WKUserContentController alloc] init];
// 添加 JS
[wkUController addUserScript:wkUScript];
[wkUController addScriptMessageHandler:self name:@"webShare"];
// 配置
WKWebViewConfiguration *wkWebConfig = [[WKWebViewConfiguration alloc] init];
wkWebConfig.userContentController = wkUController;
_webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:wkWebConfig];
NSString * htmlPath = [[NSBundle mainBundle] pathForResource:@"local" ofType:@"html"];
NSString * appHtml = [NSString stringWithContentsOfFile:htmlPath encoding:NSUTF8StringEncoding error:nil];
[_webView loadHTMLString:appHtml baseURL:nil];
}
return _webView;
}
- (void)dealloc{
[[_webView configuration].userContentController removeAllUserScripts];
[[_webView configuration].userContentController removeScriptMessageHandlerForName:@"webShare"];
}
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
NSLog(@"js oc name:%@ body:%@",message.name,message.body);
}
html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div>
<button onclick="postMessage();">发消息</button>
</div>
<script>
function postMessage(){
alert('123')
var message = {'title':'title','url':'www.baidu.com'}
window.webkit.messageHandlers.webShare.postMessage({body: message});
}
</script>
</body>
</html>