You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何在iOS默认「通话」弹窗的呼叫/取消操作中获取回调或通知?

获取iOS通话弹窗的用户操作回调

你遇到的这个问题其实是UIApplication.open(_:options:completionHandler:)的设计逻辑导致的——tel://链接是由系统接管的,completionHandler只会在系统成功弹出通话确认弹窗时立刻返回true,它完全不会等待用户点击「呼叫」或「取消」的操作,所以这个回调根本没法用来捕获用户的选择。

要拿到用户在通话弹窗的操作结果,你需要借助CallKit框架中的CXCallObserver,它能监听系统内所有通话的状态变化,包括你通过tel://发起的呼叫。

具体实现步骤

  1. 首先导入CallKit框架:
import CallKit
  1. 在你的视图控制器(或合适的类)中创建CXCallObserver实例,并设置代理:
class YourCallHandlerViewController: UIViewController {
    // 声明通话观察者
    private let callObserver = CXCallObserver()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置代理,指定在主队列处理回调(方便更新UI)
        callObserver.setDelegate(self, queue: DispatchQueue.main)
    }
    
    // 发起呼叫的方法
    func initiateCall(to phoneNumber: String) {
        guard let callURL = URL(string: "tel://\(phoneNumber)") else {
            print("无效的电话号码")
            return
        }
        // 直接打开tel链接,不需要completionHandler了
        UIApplication.shared.open(callURL)
    }
}
  1. 实现CXCallObserverDelegate代理方法,监听通话状态变化:
extension YourCallHandlerViewController: CXCallObserverDelegate {
    func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
        // 先判断是不是当前App发起的呼出通话
        guard call.isOutgoing else { return }
        
        // 用户点击了「呼叫」且通话已连接
        if call.hasConnected {
            print("用户确认呼叫,通话已接通")
            // 这里可以处理呼叫成功的业务逻辑,比如记录通话日志
        }
        
        // 用户取消了呼叫,或者通话结束
        if call.hasEnded {
            // 可以结合call.hasConnected来区分:如果hasConnected为false,说明用户取消了呼叫
            let didCancel = !call.hasConnected
            if didCancel {
                print("用户取消了呼叫")
                // 处理取消呼叫的逻辑
            } else {
                print("通话正常结束")
            }
        }
    }
}

关键说明

  • CXCallObserver不需要额外的权限配置,只要导入CallKit框架就能使用。
  • 代理方法会监听系统中所有通话的变化,所以一定要用call.isOutgoing过滤掉非当前App发起的通话,避免无关的回调干扰。
  • 状态区分逻辑:
    • 用户点击「取消」:通话不会进入hasConnected状态,直接触发hasEnded
    • 用户点击「呼叫」:会先进入连接中状态,然后触发hasConnected,通话结束时触发hasEnded

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

火山引擎 最新活动