前言
目前App基本都需要嵌入大量H5頁面, 這就需要App提供與JS交互能力, 作者這篇就簡單整理WKWebView使用常見問題.
一. WKWebView處理window.open問題
- 1. WKWebView加載頁面, 當(dāng)頁面使用window.open跳轉(zhuǎn)時候, 無響應(yīng), 需要實現(xiàn)WKUIDelegate協(xié)議實現(xiàn)
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
WKFrameInfo *frameInfo = navigationAction.targetFrame;
if (![frameInfo isMainFrame]) {
//1. 本頁跳轉(zhuǎn)
[webView loadRequest:navigationAction.request];
//2. 獲取url 打開新的 vc 實現(xiàn)跳轉(zhuǎn)到新頁面
//NSString *urlStr = [[navigationAction.request URL] absoluteString];
}
return nil;
}
注意 :
1- 使用 window.open 在移動端可能引發(fā)兼容問題, 建議前端對移動端標(biāo)簽使用location.href處理
2- ajax 處理window.open時候, 同步時可以響應(yīng)跳轉(zhuǎn), 異步時不會響應(yīng)跳轉(zhuǎn)
$.ajax({
url: '',
async: true,
complete: function (xhr) {
window.open("http://www.baidu.com");
}
});
二. WKWebView處理a標(biāo)簽問題
- 1. WKWebView加載頁面, 當(dāng)頁面使用a標(biāo)簽跳轉(zhuǎn)時 跳轉(zhuǎn)方式 (1)本頁跳轉(zhuǎn)target="_self", webview可以正常跳轉(zhuǎn); (2)新頁面跳轉(zhuǎn)target="_blank", webview無響應(yīng), 需要進(jìn)行處理, 才能跳轉(zhuǎn)
方案1: 不建議使用
- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{
// 將a標(biāo)簽 跳轉(zhuǎn)方式全部改為本頁
[webView evaluateJavaScript:@"var aArr = document.getElementsByTagName('a');for(var i=0;i<aArr.length;i++){aArr[i].setAttribute('target','');}" completionHandler:nil];
}
方案2: WKNavigationDelegate協(xié)議實現(xiàn)
-(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協(xié)議實現(xiàn)
-(WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
WKFrameInfo *frameInfo = navigationAction.targetFrame;
if (![frameInfo isMainFrame]) {
// 可創(chuàng)建新頁面打開 [WebView new]
// 也可重新加載本頁面 [webView loadRequest:navigationAction.request];
}
return nil;
}
注意 : 如果方案2與方案3 代碼中均實現(xiàn), 程序會先執(zhí)行方案2
三. WKWebView處理alert 問題
- WKWebView加載頁面, 當(dāng)頁面使用alert()睬愤、confirm()和prompt(),默認(rèn)無響應(yīng). 若要正常使用這三個方法橘霎,需要實現(xiàn)WKUIDelegate中的三個方法模擬JS的這三個方法
JS 處理實現(xiàn)方法
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();需要被執(zhí)行, 不然會引發(fā)crash.
四. WKWebView與JS簡單交互
-WKWebView加載頁面, 當(dāng)需要給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) {
// 進(jìn)行業(yè)務(wù)處理
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調(diào)用 evaluateJavaScript:completionHandler:方法, 要確保前端的JS方法不在閉包中, 如window.onload = function() {} 中的方法就無法調(diào)用.
2 如果交互復(fù)雜 可以使用 WebViewJavascriptBridge 實現(xiàn)
五. WKWebView相關(guān)文檔
WKWebView 那些坑
讓 WKWebView 支持 NSURLProtocol
以 上 !