iOS WKWebView/WebKit中如何将带target="_blank"的URL在Safari打开?
核心失败原因
- 方法作用域错误:当前代码实现的
webView(_:createWebViewWith:for:windowFeatures:)WKUIDelegate方法,写在了ViewController类的闭合大括号外部,属于全局作用域的函数,根本不会被设置了uiDelegate的webView识别为回调方法,无论怎么调整逻辑都不会触发。 - 跳转逻辑方向错误:就算方法被正常触发,当前代码碰到非主框架的
target="_blank"链接时,会直接把请求回传给当前webView加载,完全没有唤起系统Safari的执行逻辑。
正确实现逻辑
- 把所有WK相关的代理方法移动到ViewController类内部,保证回调链路通畅。
- 针对非主框架触发的跳转(即带
target="_blank"属性的链接),提取请求中的合法URL,调用系统能力唤起Safari打开,不再将请求加载到当前的webView实例中。 - 增加链接合法性校验,仅处理http/https协议的网页链接,避免异常链接触发无效系统跳转。
修正后的可直接运行代码
import UIKit import WebKit class ViewController: UIViewController, WKUIDelegate, WKNavigationDelegate { @IBOutlet weak var webView: WKWebView! override func viewDidLoad() { super.viewDidLoad() webView.uiDelegate = self webView.navigationDelegate = self guard let startURL = URL(string: "https://example.com") else { return } webView.load(URLRequest(url: startURL)) } // 类内部的WKUIDelegate回调方法 func webView(_ webView: WKWebView, createWebViewWith configuration: WKWebViewConfiguration, for navigationAction: WKNavigationAction, windowFeatures: WKWindowFeatures) -> WKWebView? { // 主框架发起的正常站内跳转,直接返回nil,交由webView正常加载 if let targetFrame = navigationAction.targetFrame, targetFrame.isMainFrame { return nil } // 拦截非主框架发起的跳转,即带target="_blank"属性的链接 guard let targetURL = navigationAction.request.url, let urlScheme = targetURL.scheme, urlScheme == "http" || urlScheme == "https" else { return nil } // 唤起系统默认Safari浏览器打开目标链接 UIApplication.shared.open(targetURL, options: [:], completionHandler: nil) // 返回nil表示不新建额外的WKWebView实例加载目标链接 return nil } }
常见踩坑提醒
- 常规iOS应用不需要额外配置Info.plist权限,即可唤起Safari打开http/https类的网页链接。
- 该逻辑可以捕获所有带
target="_blank"属性的链接跳转,哪怕目标地址后续有服务端重定向,也会在首次触发新窗口跳转的节点被拦截处理,不会出现漏判。
内容的提问来源于stack exchange,提问作者knoxbot
相关产品推荐
相关产品推荐

