前言
目前App基本都需要嵌入大量H5页面, 这就需要App提供与JS交互能力, 作者这篇就简单整理WKWebView使用常见问题.
一. WKWebView处理window.open问题
- 1. WKWebView加载页面, 当页面使用window.open跳转时候, 无响应, 需要实现WKUIDelegate协议实现
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
WKFrameInfo *frameInfo = navigationAction.targetFrame;
if (![frameInfo isMainFrame]) {
//1. 本页跳转
[webView loadRequest:navigationAction.request];
//2. 获取url 打开新的 vc 实现跳转到新页面
//NSString *urlStr = [[navigationAction.request URL] absoluteString];
}
return nil;
}
注意 :
1- 使用 window.open 在移动端可能引发兼容问题, 建议前端对移动端标签使用location.href处理
2- ajax 处理window.open时候, 同步时可以响应跳转, 异步时不会响应跳转
$.ajax({
url: '',
async: true,
complete: function (xhr) {
window.open("http://www.baidu.com");
}
});
二. WKWebView处理a标签问题
- 1. WKWebView加载页面, 当页面使用a标签跳转时 跳转方式 (1)本页跳转target="_self", webview可以正常跳转; (2)新页面跳转target="_blank", webview无响应, 需要进行处理, 才能跳转
方案1: 不建议使用
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
// 将a标签 跳转方式全部改为本页
[webView evaluateJavaScript:@"var aArr = document.getElementsByTagName('a');for(var i=0;i<aArr.length;i++){aArr[i].setAttribute('target','');}" completionHandler:nil];
}
方案2: WKNavigationDelegate协议实现
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
// webview 本页重新加载
if (navigationAction.targetFrame == nil) {
[webView loadRequest:navigationAction.request];
}
decisionHandler(WKNavigationActionPolicyAllow);
return;
}
方案3: WKUIDelegate协议实现
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
WKFrameInfo *frameInfo = navigationAction.targetFrame;
if (![frameInfo isMainFrame]) {
// 可创建新页面打开 [WebView new]
// 也可重新加载本页面 [webView loadRequest:navigationAction.request];
}
return nil;
}
注意 : 如果方案2与方案3 代码中均实现, 程序会先执行方案2
三. WKWebView处理alert 问题
- WKWebView加载页面, 当页面使用alert()、confirm()和prompt(),默认无响应. 若要正常使用这三个方法,需要实现WKUIDelegate中的三个方法模拟JS的这三个方法
JS 处理实现方法
function showAlert() {
alert("js_alertMessage");
}
function showConfirm() {
confirm("js_confirmMessage");
}
function showPrompt() {
prompt("js_prompt", "js_prompt_defaultMessage");
}
App 处理
//! alert(message)
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
completionHandler();
}
//! confirm(message)
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
completionHandler();
}
//! prompt(prompt, defaultText)
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *))completionHandler {
completionHandler();
}
注意: completionHandler();需要被执行, 不然会引发crash.
四. WKWebView与JS简单交互
-WKWebView加载页面, 当需要给js简单交互, 可如下处理
// JS 处理
document.getElementById("btn").onclick = function () {
var url = "APP://action?params";
window.location.href = url;
}
// App 处理
-(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
if ([navigationAction.request.URL.scheme caseInsensitiveCompare:@"APP"] == NSOrderedSame) {
// 进行业务处理
decisionHandler(WKNavigationActionPolicyCancel);
}else{
if (navigationAction.targetFrame == nil) {
[webView loadRequest:navigationAction.request];
}
decisionHandler(WKNavigationActionPolicyAllow);
}
return;
}
// App 处理
NSString *func = [NSString stringWithFormat:@"loadData('%@', '%@')", @"aaa", @"bbb"];
[webView evaluateJavaScript:func completionHandler:nil];
// JS 处理
function loadData(action, params){
document.getElementById("returnValue").innerHTML = action + '?' + params;
}
注意:
1 webView调用 evaluateJavaScript:completionHandler:方法, 要确保前端的JS方法不在闭包中, 如window.onload = function() {} 中的方法就无法调用.
2 如果交互复杂 可以使用 WebViewJavascriptBridge 实现
五. WKWebView相关文档
WKWebView 那些坑
让 WKWebView 支持 NSURLProtocol
以 上 !