You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何禁用iPad端WKWebView中点击电话号码弹出的弹窗?

如何在iPad上拦截WKWebView中的电话号码点击并执行自定义操作?

我之前也踩过这个iPad上的坑——iPhone上用WKNavigationDelegate的decidePolicyFor方法能顺利拦截电话链接的点击,但到了iPad上,系统直接弹出拨号弹窗,那个代理方法根本没机会触发!下面分享两个亲测有效的解决方案:

方案一:注入JavaScript提前拦截电话链接点击

因为iPad上系统会直接识别tel:链接并触发系统动作,完全不走导航代理流程,所以我们可以通过注入JS代码,在网页层面提前拦截所有电话链接的点击事件,再把消息传递给原生代码执行自定义操作。

步骤1:在网页加载完成后注入拦截JS

实现WKNavigationDelegate的didFinish方法,注入监听点击的脚本:

func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    // 监听页面所有点击事件,拦截tel:链接
    let interceptPhoneJS = """
    document.addEventListener('click', function(e) {
        let targetElement = e.target;
        // 向上遍历找到a标签
        while (targetElement && targetElement.tagName !== 'A') {
            targetElement = targetElement.parentNode;
        }
        // 判断是否是电话链接
        if (targetElement && targetElement.href && targetElement.href.startsWith('tel:')) {
            e.preventDefault(); // 阻止系统默认行为
            // 把链接传递给原生
            window.webkit.messageHandlers.phoneLinkClicked.postMessage(targetElement.href);
        }
    }, true);
    """
    
    webView.evaluateJavaScript(interceptPhoneJS) { result, error in
        if let error = error {
            print("注入拦截脚本失败:\(error.localizedDescription)")
        }
    }
}

步骤2:配置WKUserContentController接收JS消息

在初始化WKWebView时,添加消息处理器,用来接收JS传递的电话链接:

// 初始化WKUserContentController
let userContentController = WKUserContentController()
// 添加消息处理器,name要和JS里的一致
userContentController.add(self, name: "phoneLinkClicked")

// 配置WKWebView
let webConfig = WKWebViewConfiguration()
webConfig.userContentController = userContentController

// 创建WKWebView
let webView = WKWebView(frame: view.bounds, configuration: webConfig)
webView.navigationDelegate = self
view.addSubview(webView)

步骤3:实现WKScriptMessageHandler协议处理消息

让你的ViewController遵守WKScriptMessageHandler协议,接收并处理JS传来的电话链接:

extension YourViewController: WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        guard message.name == "phoneLinkClicked", let telUrl = message.body as? String else {
            return
        }
        
        // 提取电话号码,执行自定义操作
        let phoneNumber = telUrl.replacingOccurrences(of: "tel:", with: "")
        print("用户点击了电话号码:\(phoneNumber)")
        
        // 这里可以写你的自定义逻辑,比如弹出自己的确认弹窗,或者直接调用拨号
        // 示例:UIAlertController确认拨号
        let alert = UIAlertController(title: "拨打电话", message: phoneNumber, preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "取消", style: .cancel))
        alert.addAction(UIAlertAction(title: "拨号", style: .default) { _ in
            if let callUrl = URL(string: telUrl) {
                UIApplication.shared.open(callUrl)
            }
        })
        present(alert, animated: true)
    }
}

方案二:禁用WKWebView的自动电话识别(简单但有局限性)

如果你不需要网页自动把文本识别为电话链接(比如不需要显示下划线样式),可以直接关闭WKWebView的自动电话检测功能,这样点击电话链接就会走decidePolicyFor代理方法了,和iPhone上的行为一致。

代码实现

初始化WKWebView时修改配置:

let webConfig = WKWebViewConfiguration()
// 移除自动检测电话号码的类型
webConfig.dataDetectorTypes.remove(.phoneNumber)

let webView = WKWebView(frame: view.bounds, configuration: webConfig)
webView.navigationDelegate = self
view.addSubview(webView)

然后就可以用你原来的decidePolicyFor方法拦截了:

func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) {
    guard let url = navigationAction.request.url, url.scheme == "tel" else {
        decisionHandler(.allow)
        return
    }
    
    // 执行你的自定义操作
    let phoneNumber = url.absoluteString.replacingOccurrences(of: "tel:", with: "")
    print("拦截到电话链接:\(phoneNumber)")
    
    // 取消系统默认导航,执行自己的逻辑
    decisionHandler(.cancel)
    
    // 示例自定义逻辑:弹出确认弹窗
    let alert = UIAlertController(title: "确认拨号", message: phoneNumber, preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "取消", style: .cancel))
    alert.addAction(UIAlertAction(title: "拨号", style: .default) { _ in
        UIApplication.shared.open(url)
    })
    present(alert, animated: true)
}

注意

这个方案的缺点是:网页里的纯文本电话号码不会被自动识别为可点击的链接了,如果你的业务需要保留这个样式,建议用方案一。


内容的提问来源于stack exchange,提问作者Nick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 06:16:17