WKWebview與JSBridge日常使用記錄

最近項目中因爲涉及到WKWebview與JSBridge的交互有點多,目前採用的方案把已知問題都解決了。怕自己遺忘,所以記錄下來,也供大家參考。
前情提要
應用是新聞類App,內部視圖較爲複雜且嵌入多方廣告套件,多方考量之下,採取原生嵌套H5來實現,頂部nav部分由原生來做(類似於今日頭條的頂部導航欄和頻道欄),中間內容部分由H5來做,大方向定下來之後,最主要涉及的就是原生和H5的交互問題,JSBridge使用的是WebViewJavascriptBridge庫,是一個簡單易用的庫,而且團隊在之前的項目中也一直在使用,已經較爲熟練。
問題記錄
然而在使用過程中還是遇到了問題,問題記錄如下:

同域名下加載不同網頁,WKNavigationDelegate的didStartProvisionalNavigation沒有回調。
廣告套件H5無法拿到跳轉url,故不能通過JSBridge傳給原生。
廣告套件種類過多,想要單純靠WKNavigationDelegate的didStartProvisionalNavigation並不可靠。
H5那邊有重定向,iOS這邊本可以不用管,但某些網頁重定向到了Http鏈接,Apple禁止了Http,大家應該都知道,只有添加白名單纔可加載,不然會出現白屏。
就算是Https也會存在不受信任或者過期的情況,不作處理也會出現白屏。

問題處理

同域名下加載不同網頁,WKNavigationDelegate的didStartProvisionalNavigation沒有回調。

這個可以JSBridge傳給原生,原生實現新頁面跳轉,JSBridge的註冊記得寫在webview加載的後面,具體使用方法可以去WebViewJavascriptBridge庫查看,簡單來說,H5通知原生的場景,H5要調callHandler方法,原生要調registerHandler方法。反過來,原生通知H5的場景,H5要調registerHandler方法,原生要調callHandler方法。

廣告套件H5無法拿到跳轉url,故不能通過JSBridge傳給原生。

廣告套件是外部鏈接,用WKNavigationDelegate的didStartProvisionalNavigation滿足了大多數場景。
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
// startLoading()
//處理廣告套件的跳轉
if let url = webView.url, url != self.url, !url.absoluteString.contains(Settings.baseH5Url) {
webView.stopLoading()
self.openDetailVC(url: url, title: “新聞詳情”)
}
}

複製代碼
廣告套件種類過多,想要單純靠WKNavigationDelegate的didStartProvisionalNavigation並不可靠。

當didStartProvisionalNavigation不可靠時,可以嘗試用另一個代理。
func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? {
if let url = navigationAction.request.url, url != self.url, !url.absoluteString.contains(Settings.baseH5Url) {
self.openDetailVC(url: url, title: “新聞詳情”)
}
return nil
}
複製代碼
H5那邊有重定向,iOS這邊本可以不用管,但某些網頁重定向到了Http鏈接,Apple禁止了Http,大家應該都知道,只有添加白名單纔可加載,不然會出現白屏。

Http鏈接未知,添加白名單就顯得不現實,採取折中方案,彈框告知用戶是Http鏈接,可以跳轉Safari瀏覽器繼續觀看,重定向攔截也是webview的一個代理方法。
func webView(_ webView: WKWebView, didReceiveServerRedirectForProvisionalNavigation navigation: WKNavigation!) {
//http增加彈框,防止http加載不了出現白屏
if let webViewUrl = webView.url, webViewUrl.absoluteString.contains(“http://”) {
showAlert(title: “http訪問”, message: “http訪問不安全,是否允許打開瀏覽器訪問”, buttonTitles: [“取消”, “確認”], highlightedButtonIndex: 1) { index in
if index == 1 {
if UIApplication.shared.canOpenURL(webViewUrl) {
if #available(iOS 10.0, *) {
UIApplication.shared.open(webViewUrl, options: [:], completionHandler: nil)
} else {
UIApplication.shared.openURL(webViewUrl)
}
}
}
self.navigationController?.popViewController(animated: true)
}
}
}
複製代碼
就算是Https也會存在不受信任或者過期的情況,不作處理也會出現白屏。

webview還有一個專門處理證書信任的代理方法,設爲信任即可。
func webView(_ webView: WKWebView, didReceive challenge: URLAuthenticationChallenge, completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
if challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust {
let card = URLCredential.init(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, card)
}
}

複製代碼目前有用到的方法基本都列下了,webview還有一個代理是監聽點擊事件的,這個代理的返回過於頻繁複雜,調試發現在頁面加載的時候也會回調,不太好處理邏輯,但是知道一下留作備用。
optional func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void)
複製代碼小結
其實WKWebview我們團隊已經在上線App中使用很久了,今年Apple就會要求開發者強制使用WKWebview了,對開發者而言,其實沒多大差別,方法名都差不多,對我們團隊而言最大的差別可能就是不能在storeboard中拖一個webview進去了,畢竟storeboard用慣了。感慨一下,我們能想到的問題,Apple基本都想到了。所以沒有解決不了的場景,只有沒有下苦功的我們。😂😂😂

發佈了15 篇原創文章 · 獲贊 0 · 訪問量 535
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章