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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章