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
相关产品推荐
相关产品推荐

