iOS Swift中WKWebView点击时段触发打开日历应用问题排查
解决WKWebView意外打开iOS日历应用的问题
针对你遇到的WKWebView加载预约页面时,点击时段意外唤起日历应用的问题,可以通过拦截所有外部跳转请求来彻底阻止应用打开其他App,具体实现如下:
核心解决方案
通过实现WKNavigationDelegate和WKUIDelegate的相关方法,拦截所有试图打开外部应用的请求:
1. 给WebView设置UIDelegate
在viewDidLoad中添加:
webView.uiDelegate = self
2. 实现导航代理的拦截方法
添加WKNavigationDelegate的decidePolicyFor方法,可选择仅允许加载指定域名内的内容,或直接全部阻止外部跳转:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { // 仅允许加载目标预约页面的域名,替换成你的实际域名 guard let host = navigationAction.request.url?.host, host == "你的预约页面域名" else { // 阻止外部跳转 decisionHandler(.cancel) return } // 允许同域名内的跳转 decisionHandler(.allow) }
如果需要完全阻止所有外部应用跳转,不管域名,可简化为:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { // 拦截所有外部跳转请求 if navigationAction.targetFrame == nil || navigationAction.navigationType == .linkActivated { decisionHandler(.cancel) return } decisionHandler(.allow) }
3. 处理JS触发的跳转(如window.open)
实现WKUIDelegate的openURL方法,阻止通过JavaScript触发的外部跳转:
extension AppointmentVC: WKUIDelegate { func webView(_ webView: WKWebView, openURL url: URL, options: [WKOpenURLOptionsKey : Any], completionHandler: @escaping (Bool) -> Void) { // 直接阻止所有外部打开请求 completionHandler(false) } }
修改后的完整代码
class AppointmentVC: UIViewController, WKNavigationDelegate, WKUIDelegate { @IBOutlet weak var webView: WKWebView! var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView() override func viewDidLoad() { super.viewDidLoad() navigationController?.setNavigationBarHidden(false, animated: false) webView.navigationDelegate = self webView.uiDelegate = self // 设置UIDelegate webView.customUserAgent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36" webView.allowsLinkPreview = false webView.allowsBackForwardNavigationGestures = true activityIndicator.center = self.view.center activityIndicator.hidesWhenStopped = true activityIndicator.style = UIActivityIndicatorView.Style.gray view.addSubview(activityIndicator) activityIndicator.startAnimating() let url: URL = URL(string: "https://...")! let urlRequest: URLRequest = URLRequest(url: url) webView.load(urlRequest) } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { activityIndicator.stopAnimating() } // 拦截导航跳转 func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { // 替换成你的预约页面域名,仅允许同域名跳转 guard let host = navigationAction.request.url?.host, host == "your-appointment-domain.com" else { decisionHandler(.cancel) return } decisionHandler(.allow) } // 处理JS触发的外部打开请求 func webView(_ webView: WKWebView, openURL url: URL, options: [WKOpenURLOptionsKey : Any], completionHandler: @escaping (Bool) -> Void) { completionHandler(false) } }
补充说明
你之前尝试的修改User Agent、禁用链接预览无法解决问题,是因为这类跳转通常是页面通过JavaScript触发的自定义跳转,或是系统对时段文本的智能识别跳转,只有通过代理拦截所有跳转请求才能彻底阻止。
内容的提问来源于stack exchange,提问作者Vlad Slavskii
相关产品推荐
相关产品推荐

