参考:
关于WKWebView
与UIWebView
之间的区别,本文就不在说明,本文只使用WKWebView
。
效果图如下:
html代码:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf8">
<script language="javascript">
function loadURL(url) {
window.location.href = url
}
function locationClick() {
loadURL("scheme://getLocation");
}
function shake() {
loadURL("scheme://shake");
}
function setLocation(location) {
alert(location)
document.getElementById("returnValue").value = location;
}
</script>
</head>
<body>
<h1>这是按钮调用</h1>
<input type="button" value="获取定位" onclick="locationClick()" /><br><br>
<input type="button" value="震动一下" onclick="shake()" /><br><br>
<h1>这是文件上传</h1>
<input type="file" /><br><br>
<h1>这是回调结果展示区</h1>
<textarea id ="returnValue" type="value" rows="5" cols="50"></textarea>
</body>
</html>
以获取定位这个按钮为例说明OC和JS互相调用代码执行流程:
- 初始化
WKWebView
加载本地html文件。 - 点击web中的按钮,web发起URL请求。
- URL请求被
WKNavigationDelegate
中的代理方法拦截。根据自定义的URL识别使用不同的处理方式。如:在- (void)getLocation
方法中调用JS的setLocation
函数。 - JS的
setLocation
函数执行JS的alert()
函数,被WKUIDelegate
中的代理方法捕获,调用iOS原生的弹框。
详细代码说明
-
初始化
WKWebView
加载本地html文件- (void)initWKWebView { // 1 WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init]; configuration.userContentController = [WKUserContentController new]; WKPreferences *preferences = [WKPreferences new]; preferences.javaScriptCanOpenWindowsAutomatically = YES; preferences.minimumFontSize = 40.0; configuration.preferences = preferences; self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration]; // 2 NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"index.html" ofType:nil]; NSURL *fileURL = [NSURL fileURLWithPath:urlStr]; [self.webView loadFileURL:fileURL allowingReadAccessToURL:fileURL]; self.webView.navigationDelegate = self; self.webView.UIDelegate = self; [self.view addSubview:self.webView]; }
- 1
WKWebView
的一些参数配置 - 2 加载本html
- 1
-
URL请求被
WKNavigationDelegate
中的代理方法拦截。也就是JS调用了OC#pragma mark - WKNavigationDelegate - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { NSURL *URL = navigationAction.request.URL; NSString *scheme = [URL scheme]; if ([scheme isEqualToString:@"scheme"]) { [self handleCustomAction:URL]; decisionHandler(WKNavigationActionPolicyCancel); return; } decisionHandler(WKNavigationActionPolicyAllow); }
-
OC 调用 JS
- (void)getLocation { // 将结果返回给js NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')",@"上海市浦东新区"]; [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) { NSLog(@"%@----%@",result, error); }]; }
- JS代码被当成字符串调用
-
completionHandler
是JS代码被调用后回调
-
JS中alert弹窗被
WKUIDelegate
中的代理方法捕获,调用iOS原生的弹框。#pragma mark - WKUIDelegate - (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler { UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { completionHandler(); }]]; [self presentViewController:alert animated:YES completion:nil]; }
最后,html中的文件input可以直接调用iOS的图片库,相机和文件。
代码: 90-iOSJS/OCJS1