CallKit – How to Configure It?

CallKit – How to Configure It?

iOS 10 offers many new features. One of them is CallKit, the framework which allows our application to seamlessly integrate with the user interface of a phone. CallKit may be used in applications to let users receive incoming calls and perform outgoing calls with the phone-provided UI. VoIP call can be muted or suspended. It is also possible to make video calls.

Preparing the project

The first step is to prepare receiving VoIP notifications.

Background modes - Voice over IP

Configuring VoIP notifications

To configure the application to receive notifications, import framework PushKit to our AppDelegate file and create an object PKPushRegistry. Be sure to set the delegate of the newly created object as self, and set its type as VoIP:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
        let pushRegistry = PKPushRegistry(queue: DispatchQueue.main)
        pushRegistry.delegate = self
        pushRegistry.desiredPushTypes = [.voIP]

        return true

Functions used for storing credentials on the server for the active user and processing pushs are:

func pushRegistry(_ registry: PKPushRegistry, didUpdate credentials: PKPushCredentials, forType type: PKPushType) {
            //Store push credentials on server for the active user.

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {

Supporting received notifications

The final step is to parse the data received from the function didReceiveIncomingPushWith, which, among other things, can wake the phone from the state of being locked.

func pushRegistry(_ registry: PKPushRegistry, didReceiveIncomingPushWith payload: PKPushPayload, forType type: PKPushType) {
        guard type == .voIP else { return }

        if let uuidString = payload.dictionaryPayload["UUID"] as? String,
           let handle = payload.dictionaryPayload["handle"] as? String,
           let hasVideo = payload.dictionaryPayload["hasVideo"] as? Bool,
           let uuid = UUID(uuidString: uuidString)
             // Handle incoming call

Setting up CallKit

The first step is to create a class to handle incoming calls by extending the class CXProviderDelegate.

final class ProviderDelegate: NSObject, CXProviderDelegate {
    private let provider: CXProvider

The next step is to configure the provider.

static var providerConfiguration: CXProviderConfiguration {
        let localizedName = NSLocalizedString("APPLICATION_NAME", comment: "name")
        let providerConfiguration = CXProviderConfiguration(localizedName: localizedName)

        providerConfiguration.supportsVideo = true

        providerConfiguration.maximumCallsPerCallGroup = 1

        providerConfiguration.supportedHandleTypes = [.phoneNumber]

        if let iconMaskImage = UIImage(named: "wideo") {
            providerConfiguration.iconTemplateImageData = UIImagePNGRepresentation(iconMaskImage)

        providerConfiguration.ringtoneSound = "Ringtone.caf"

        return providerConfiguration

The last step is to provide an initializer, add the reportIncomingCall function responsible for the transfer of an incoming call to the system and to add providerDidReset function which is called when the provider is restarted.

init() {
        provider = CXProvider(configuration: type(of: self).providerConfiguration)
        provider.setDelegate(self, queue: nil)

func reportIncomingCall(uuid: UUID, handle: String, hasVideo: Bool = false, completion: ((NSError?) -> Void)? = nil) {
        // Construct a CXCallUpdate describing the incoming call, including the caller.
        let update = CXCallUpdate()
        update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
        update.hasVideo = hasVideo

        // Report the incoming call to the system
        provider.reportNewIncomingCall(with: uuid, update: update) { error in
            completion?(error as? NSError)

func providerDidReset(_ provider: CXProvider) {
        print("Provider did reset")
            End any ongoing calls if the provider resets, and remove them from the app's list of calls,
            since they are no longer valid.

This is only an introduction, and if you would like to learn more about this, I recommend reading this.

You can find a lot of information and a sample application there.


Wojtek Byczkowski

iOS Developer at Holdapp for 5 years. Wojtek believes that less is more in software development and always puts efficiency first when working on projects. Apart from programming, he also has a passion for sports. If you’d like to talk about football or speedway, Wojtek’s definitely your man.

Learn more

How to Send iOS Notifications in Different Languages? Guide to Dynamic Localization

The best way to set a connection between a user, provider, and an app? System notifications. They allow users to get the latest news in no time. This solution is easy to implement in apps dedicated to one market. But it gets complicated when the messages must be displayed in many languages. In such cases, the dynamic localization of remote notifications can be a real game-changer.

Read more

Promises on the Example of PromiseKit in Objective-C

Sooner or later every programmer encounters the problem of synchronous execution of certain actions. For example: get user information from the API, parse server response, save data to the database, update the view, and many others. To make it even more, at some of these stages you still need to deal with error handling. What should you do exactly?

Read more

Project estimation

Let us know what product you want to build and how we can help you.

Why choose us?

Logo Mobile Trends Awards

Mobile Trends Awards 2021

Winning app in

Nagroda Legalnych Bukmacherów

Legal Bookmakers Award 2019

Best Mobile App

Mobile Trends Awards logo

Mobile Trends Awards 2023



client reviews

Clutch logo