Xcode 12.5及Swift 5+环境下WKWebView如何打开外部链接到Safari
解决方法
现有代码的问题
- 未给
WKWebView设置navigationDelegate,导致拦截跳转的代理方法无法触发 - 跳转拦截方法内部存在重复执行的逻辑冲突,分支判断和外部执行语句重复调用了打开链接和
decisionHandler方法,会导致逻辑异常
修改步骤
- 让当前ViewController遵守
WKNavigationDelegate协议 - 初始化
WKWebView时绑定navigationDelegate - 清理拦截方法内的冗余逻辑,仅拦截http/https协议的外部跳转调用系统Safari打开,本地file协议的资源正常在WebView内加载
修正后完整代码
import UIKit import WebKit import PDFKit // 遵守WKNavigationDelegate协议 class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate { var webView: WKWebView! override func loadView() { let webConfiguration = WKWebViewConfiguration() webView = WKWebView(frame: .zero, configuration: webConfiguration) webView.uiDelegate = self // 绑定navigationDelegate webView.navigationDelegate = self view = webView } override func viewDidLoad() { super.viewDidLoad() guard let url = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "www") else { return } webView.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent()) let request = URLRequest(url: url) webView.load(request) } // WKNavigationDelegate 跳转拦截方法 func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { // 仅拦截用户点击触发的链接跳转 guard navigationAction.navigationType == .linkActivated, let url = navigationAction.request.url, let scheme = url.scheme else { decisionHandler(.allow) return } // 判断协议为http/https则跳系统Safari if scheme == "http" || scheme == "https" { UIApplication.shared.open(url) decisionHandler(.cancel) return } // 其他协议(比如本地的file协议)正常加载 decisionHandler(.allow) } }
说明
本地www文件夹内的资源使用file协议加载,不会被上述拦截逻辑命中,会正常在WebView内渲染,只有用户点击的外部http/https链接会被拦截跳转到系统Safari打开。
内容的提问来源于stack exchange,提问作者ralphb
相关产品推荐
相关产品推荐

