使用 CTCallCenter (Swift) 检测 iOS 上的 phone 呼叫

Detect phone calls on iOS with CTCallCenter (Swift)

我想尝试在我的应用程序中检测传入的 phone 呼叫。我从头开始创建了一个新的 Swift 项目,只是为了尝试一些代码。我唯一做的就是在每个新项目创建的 ViewController 中导入 CoreTelephony,我还将 viewDidLoad() 更改为:

    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    let callCenter = CTCallCenter()
    NSLog("start")

    callCenter.callEventHandler = {[weak self] (call: CTCall) -> () in

        self?.label.text = call.callState
        NSLog("Call state")
        NSLog(call.callState)

    }

我也尝试过不使用 [weak self],因为我是 swift 的新手,不确定它需要什么。

当我 运行 我的新小应用程序通过 XCode 在我的 phone 上时,接听电话、断开连接或其他任何事情都没有任何反应。从来没有错误。我是否需要做更多的事情才能使用 CoreTelephony 框架和 CTCallCenter?

问候 约翰

这是对我上面的评论的扩展。

Try making callCenter a property of your view controller instead of just a variable in viewDidLoad.

当您在方法中定义变量时,该变量及其值仅存在于该方法中。当该方法完成时 运行,有价值的及其值将被清理,因此它们不会继续使用内存(除非该值被其他地方使用)。

在您的例子中,您定义了 callCenter 并为其分配了一个新的 CTCallCenter 实例。但在 viewDidLoad 结束时,CTCallCenter 实例不再使用,因此它已从内存中清除。由于它已不存在,因此无法处理调用事件。

通过添加 callCenter 作为视图控制器的 属性,它将 CTCallCenter 实例的生命周期与视图控制器的生命周期联系起来。因此 CTCallCenter 只会在视图控制器从内存中清除时从内存中清除。

有关详细信息,请阅读 Automatic Reference Counting in Swift

callEventHandler 已从 iOS 10 开始弃用。

iOS 10 现在使用一个新框架来完成您正在尝试做的事情,CallKit。这是 Apple 的新框架,应该可以处理所有 phone 呼叫中断。要检测来电和去电,您可以使用 CXCallObserver。此 class 使用协议 CXCallObserverDelegate 通知已注册的代表呼叫发生变化。我发现将 AppDelegate 设置为代表效果很好。

// AppDelegate
var callObserver: CXCallObserver!

// in applicationDidFinishLaunching...
callObserver = CXCallObserver()
callObserver.setDelegate(self, queue: nil) // nil queue means main thread

extension AppDelegate: CXCallObserverDelegate {
    func callObserver(_ callObserver: CXCallObserver, callChanged call: CXCall) {
        if call.hasEnded == true {
            print("Disconnected")
        }
        if call.isOutgoing == true && call.hasConnected == false {
            print("Dialing")
        }
        if call.isOutgoing == false && call.hasConnected == false && call.hasEnded == false {
            print("Incoming")
        }

        if call.hasConnected == true && call.hasEnded == false {
            print("Connected")
        }
    }
}