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

使用CallKit发起外呼时调用CXStartCallAction请求事务报错

Troubleshooting CXStartCallAction Transaction Error in CallKit

Hey there, let's break down the common reasons why your CXStartCallAction transaction might be failing and how to fix them:

1. Missing or Incorrect CXCallController Setup

First off, make sure you have a persistent, properly initialized CXCallController instance. If it's a local variable that gets deallocated before the request completes, the transaction will fail silently or throw an error.

You should hold onto it in a dedicated call manager class or your app delegate, like this:

class CallManager {
    static let shared = CallManager()
    let callController = CXCallController()
    // Other CallKit-related properties...
}

Then reference this shared instance in your requestTransaction method.

2. Incomplete requestTransaction Implementation

Your requestTransaction method is missing the critical step of actually submitting the transaction to CallKit via CXCallController. Here's the full, correct implementation:

private func requestTransaction(_ transaction: CXTransaction, completion: ((_ error: Error?) -> Void)? = nil) {
    CallManager.shared.callController.request(transaction) { error in
        if let error = error {
            print("Transaction request failed: \(error.localizedDescription)")
            // Dig into specific CallKit error codes for more context
            if let callKitError = error as? CXErrorCodeCallControllerError {
                switch callKitError.code {
                case .transactionFailed:
                    print("Transaction failed due to invalid actions")
                case .unknownCallProvider:
                    print("Call provider is not registered with the system")
                default:
                    print("Other CallKit error: \(callKitError.code.rawValue)")
                }
            }
        } else {
            print("Transaction requested successfully")
        }
        completion?(error)
    }
}

3. Unimplemented CXProviderDelegate Methods

CallKit requires your app to handle the CXStartCallAction via the CXProviderDelegate. If you haven't implemented provider(_:perform:), the system will reject the transaction outright. Add this to your delegate class:

func provider(_ provider: CXProvider, perform action: CXStartCallAction) {
    // Here you should initiate your actual call (VoIP, direct call logic, etc.)
    // Once the call is successfully started, fulfill the action:
    action.fulfill()
    
    // If something goes wrong during call setup, fail the action with a relevant error:
    // action.fail(withError: NSError(domain: "YourAppDomain", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to start call"]))
}

Don't forget to register your CXProvider with the system during app setup:

let configuration = CXProviderConfiguration(localizedName: "Your App Name")
configuration.supportsVideo = true
configuration.maximumCallGroups = 1
let provider = CXProvider(configuration: configuration)
provider.setDelegate(self, queue: DispatchQueue.main)

4. Duplicate or Invalid UUID

Ensure the uuid passed to CXStartCallAction is unique for each call. Reusing the same UUID will cause CallKit to treat it as a duplicate request and reject it. If you're not generating it internally, add a check to guarantee uniqueness, or generate it directly in the startCall function:

private func startCall(handle: String, video: Bool = false) {
    let uuid = UUID() // Generate a new unique UUID for every call
    let handle = CXHandle(type: .phoneNumber, value: handle)
    let startCallAction = CXStartCallAction(call: uuid, handle: handle)
    startCallAction.isVideo = video
    let transaction = CXTransaction()
    transaction.addAction(startCallAction)
    requestTransaction(transaction)
}

5. Invalid Handle Format or Type

For .phoneNumber type handles, the value must follow the E.164 standard (e.g., +1234567890). If your number is in a different format (like missing the country code), CallKit might reject the request. Test with a properly formatted number, or try using .generic type temporarily to rule out format issues:

let handle = CXHandle(type: .generic, value: handle)

6. Missing Permissions

Even though CallKit doesn't require a specific permission, you'll need microphone access for voice calls. Make sure you've added NSMicrophoneUsageDescription to your Info.plist with a clear explanation, and request permission before initiating calls:

import AVFoundation

// Request mic permission before starting a call
AVAudioSession.sharedInstance().requestRecordPermission { granted in
    DispatchQueue.main.async {
        if granted {
            // Proceed with call setup
            self.startCall(handle: "1234567890")
        } else {
            // Handle permission denial (show alert to user)
        }
    }
}

Start with checking the requestTransaction implementation and CXProviderDelegate methods first—those are the most common culprits. If you're still seeing errors, print the full error details (as shown in the requestTransaction example) to get more specific info about what's going wrong.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:48:43