关于WKWebView
与UIWebView
之间的区别,本文就不在说明,本文只使用WKWebView
。
效果图如下:
html代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37<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文件1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21- (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调用了OC1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (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
1
2
3
4
5
6
7
8- (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原生的弹框。1
2
3
4
5
6
7
8
9
10
11
- (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
参考: