WKWebView启动时decidePolicyFor为何被about:blank请求触发?
问题描述
正在完成Hacking With Swift的《EasyBrowser Challenge》第一部分,要求若用户尝试访问未被允许的URL,需显示提示弹窗说明站点被拦截。
在webView(_:decidePolicyFor:decisionHandler:)方法中实现了拦截未授权主机的逻辑(代码如下),但应用启动时该方法会被URL为about:blank的请求触发,出现两次导航请求:第一次是预期的已授权站点(如apple.com),第二次是about:blank并触发拦截弹窗,且未在启动时触发重载操作。
代码片段:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { let url = navigationAction.request.url if let host = url?.host{ print(host) for website in websites { if host.contains(website){ decisionHandler(.allow) return } } } let alertController = UIAlertController(title: "Access Blocked!", message: "Website you are trying to access is blocked. Please request access.", preferredStyle: .alert) alertController.addAction(UIAlertAction(title: "Go back.", style: .cancel)) present(alertController, animated: true) print("not allowed") decisionHandler(.cancel) }
问题原因与解决方案
原因
WKWebView初始化完成后,默认会自动加载about:blank页面作为初始状态,这会触发一次导航请求。而你启动时主动加载了已授权的站点,因此又会触发第二次导航请求。当前代码未对about:blank做特殊处理,它没有主机地址(host为nil),所以会进入拦截分支,弹出弹窗。
解决方案
在拦截逻辑最开始,先判断请求的URL是否为about:blank,如果是则直接允许导航,跳过后续拦截判断:
修改后的代码:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { let url = navigationAction.request.url // 特殊处理about:blank,直接允许 if url?.absoluteString == "about:blank" { decisionHandler(.allow) return } if let host = url?.host{ print(host) for website in websites { if host.contains(website){ decisionHandler(.allow) return } } } let alertController = UIAlertController(title: "Access Blocked!", message: "Website you are trying to access is blocked. Please request access.", preferredStyle: .alert) alertController.addAction(UIAlertAction(title: "Go back.", style: .cancel)) present(alertController, animated: true) print("not allowed") decisionHandler(.cancel) }
内容的提问来源于stack exchange,提问作者brunshte
相关产品推荐
相关产品推荐

