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

iOS中如何检测通过openUrl()发起的通话已结束

嘿,这个需求我之前做类似功能的时候研究过,iOS本身没有直接提供“通话结束”的系统通知,但我们可以通过两种常用方案来实现你的需求,下面给你详细说明:

解决iOS通话结束后执行操作的方案

方法一:使用CallKit框架监听通话状态(推荐,iOS 10+)

CallKit是苹果官方提供的用于处理通话相关功能的框架,它能让我们精准监听通话的状态变化,包括通话结束。

实现步骤:

  • 首先导入CallKit框架
import CallKit
  • 创建一个CXCallObserver实例,并设置代理(记得要持有这个实例,比如作为ViewController的属性):
class YourViewController: UIViewController, CXCallObserverDelegate {
    private let callObserver = CXCallObserver()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 设置代理,指定在主队列处理回调
        callObserver.setDelegate(self, queue: DispatchQueue.main)
    }
    
    // 实现代理方法,监听通话状态变化
    func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
        // 判断通话是否已经结束,且没有其他活跃状态(比如等待、保持)
        if call.hasEnded && !call.isConnecting && !call.isOnHold {
            // 这里写入你通话结束后需要执行的代码
            print("通话已结束,执行后续操作")
            // 示例:刷新联系人数据、发送统计埋点等
        }
    }
    
    // 保留你原来的拨打电话逻辑
    func initiateCall(contactNo: String) {
        let cleanedContactNumber = Util.checkForNullString(contactNo)
        guard let callURL = URL(string: "tel://\(cleanedContactNumber)"), 
              UIApplication.shared.canOpenURL(callURL) else {
            return
        }
        
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(callURL)
        } else {
            UIApplication.shared.openURL(callURL)
        }
    }
}

注意事项:

  • 确保CXCallObserver实例被正确持有,避免被提前释放导致监听失效
  • 这个方案能精准捕获所有通话结束场景,不管是用户主动挂断还是对方挂断

方法二:监听应用前后台切换(简易方案)

如果你的需求不需要极致精准,也可以通过监听应用回到前台的事件来触发操作——因为用户拨打电话时应用会进入后台,通话结束后通常会直接回到你的应用。

实现步骤:

  • 在AppDelegate(iOS 12及以下)或SceneDelegate(iOS 13+)中监听应用激活事件:
// AppDelegate 示例(iOS 12及以下)
func applicationDidBecomeActive(_ application: UIApplication) {
    // 检查是否是刚发起过通话后回到应用
    if UserDefaults.standard.bool(forKey: "hasInitiatedCall") {
        // 执行通话结束后的操作
        print("从通话回到应用,执行后续操作")
        // 重置标记,避免重复触发
        UserDefaults.standard.set(false, forKey: "hasInitiatedCall")
    }
}

// SceneDelegate 示例(iOS 13+)
func sceneDidBecomeActive(_ scene: UIScene) {
    if UserDefaults.standard.bool(forKey: "hasInitiatedCall") {
        print("从通话回到应用,执行后续操作")
        UserDefaults.standard.set(false, forKey: "hasInitiatedCall")
    }
}
  • 在你的拨打电话方法中添加标记:
func initiateCall(contactNo: String) {
    let cleanedContactNumber = Util.checkForNullString(contactNo)
    guard let callURL = URL(string: "tel://\(cleanedContactNumber)"), 
          UIApplication.shared.canOpenURL(callURL) else {
        return
    }
    
    // 设置标记,标记即将发起通话
    UserDefaults.standard.set(true, forKey: "hasInitiatedCall")
    
    if #available(iOS 10.0, *) {
        UIApplication.shared.open(callURL)
    } else {
        UIApplication.shared.openURL(callURL)
    }
}

优缺点:

  • 优点:实现简单,不需要引入额外框架
  • 缺点:精准度不足——如果用户打完电话没有直接回到你的应用,而是先打开其他应用再回来,这个逻辑也会触发操作,不符合预期

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:11:47