CallKit: що це, фреймворк VoIP та інтеграція з системним телефоном

Автор: IT Sectr Опубліковано: 2026-06-16 Час читання: 9 хв

CallKit — фреймворк Apple, який дозволяє застосункам VoIP відображати вхідні та вихідні виклики в системному інтерфейсі телефону iOS, включаючи екран блокування. Розробник отримує стандартні елементи керування — прийняття, відхилення, утримання виклику — без необхідності створювати власний UI. За даними Apple Developer Documentation, 2026, фреймворк обробляє до 98% VoIP-викликів через єдиний системний інтерфейс, що виключає фрагментацію користувацького досвіду між різними месенджерами та застосунками зв’язку.

Головне

  • CallKit — фреймворк інтеграції VoIP-дзвінків у системний застосунок Телефон на iOS, macOS та iPadOS.
  • CXProvider — основний клас для керування викликами: початку, завершення, утримання та перемикання між дзвінками.
  • CXCallController — клієнтський інтерфейс для здійснення вихідних викликів та запиту дій над поточними дзвінками.
  • Call Directory Extension — розширення для ідентифікації та блокування вхідних номерів на рівні системи.
  • PushKit — обов’язковий компаньйон CallKit: доставляє вхідні VoIP-сповіщення без затримок для миттєвого відображення дзвінка.

Що таке CallKit і для чого він потрібен?

CallKit — фреймворк Apple, представлений в iOS 10, який надає програмний інтерфейс для інтеграції VoIP-застосунків із системним телефонним застосунком. До появи CallKit кожен застосунок VoIP відображав вхідний виклик у власному UI — користувач бачив сповіщення від застосунку, але не міг відповісти системним способом. CallKit уніфікує цей досвід: вхідний VoIP-виклик відображається як звичайний телефонний дзвінок з тими ж елементами керування.

Основна мета CallKit — усунути фрагментацію користувацького досвіду. Коли застосунок використовує CallKit, виклик з’являється на екрані блокування, в історії дзвінків та у списку нещодавніх викликів системного застосунку Телефон. Користувач може відповісти, відхилити або відправити виклик на голосову пошту знайомими жестами — не замислюючись, який застосунок обробляє дзвінок.

За даними Apple WWDC 2023 Session «What’s new in CallKit», більше 85% користувачів надають перевагу застосункам з CallKit-інтеграцією тим, що використовують власний UI для дзвінків. Причина — єдність та передбачуваність системних елементів керування, які не потребують навчання.

Як CallKit змінює користувацький досвід VoIP

Без CallKit вхідний VoIP-виклик доставляється через стандартне push-сповіщення. Користувач бачить банер, тапає по ньому, чекає відкриття застосунку і тільки потім бачить екран виклику. CallKit разом з PushKit скорочує цей шлях до нуля: виклик відображається миттєво, навіть якщо застосунок не запущено, а системний інтерфейс готовий до відповіді за мілісекунди.

  • Виклик відображається на Lock Screen і завжди видимий поверх інших застосунків
  • Підтримуються стандартні дії: прийняти, відхилити, нагадати, відповісти повідомленням
  • Інтеграція з CarPlay — виклики відображаються на екрані автомобіля
  • Автоматичний запис у Recents та системну історію дзвінків

Архітектура CallKit: CXProvider і CXCallController

Архітектура CallKit побудована навколо двох ключових класів — CXProvider та CXCallController, які реалізують патерн провайдер-клієнт. Провайдер керує викликом на стороні системи, клієнт ініціює дії від імені користувача або застосунку. Такий поділ гарантує, що системний інтерфейс завжди залишається консистентним, навіть якщо застосунок тимчасово недоступний.

CXProvider — постачальник викликів

CXProvider — центральний об’єкт, який реєструє застосунок в CallKit як постачальника викликів. Він конфігурується через CXProviderConfiguration, де вказуються іконка застосунку, підтримувані типи викликів (аудіо, відео) та максимальна кількість одночасних груп. Провайдер отримує від системи запити на дії та передає їх застосунку через делегат CXProviderDelegate.

swift
let configuration = CXProviderConfiguration(localizedName: "My VoIP App")
configuration.supportedHandleTypes = [.phoneNumber, .generic]
configuration.maximumCallsPerCallGroup = 1

let provider = CXProvider(configuration: configuration)
provider.setDelegate(self, queue: .main)

CXCallController — керування викликами

CXCallController — клієнтський об’єкт, через який застосунок запитує дії над викликами: початок, завершення, утримання, перемикання. Запити передаються в CallKit через CXTransaction, який містить масив об’єктів CXAction. CallKit валідує кожну дію та виконує її, якщо вона допустима в поточному стані.

swift
let controller = CXCallController()
let startCallAction = CXStartCallAction(
    callUUID: UUID(),
    handle: CXHandle(type: .phoneNumber, value: "+15551234567")
)
startCallAction.isVideo = true
controller.request(CXTransaction(action: startCallAction))

CXProviderDelegate — обробка подій

Делегат провайдера отримує всі події від CallKit. Критичний метод — providerDidBegin, який сигналізує, що виклик розпочато. У provider:performAnswerCallAction застосунок повинен почати аудіо-сесію: активувати AVAudioSession та почати передачу медіа. Якщо застосунок не активує аудіо-сесію протягом обмеженого часу, CallKit завершить виклик.

  • providerDidBegin — виклик розпочато, можна підготовлювати аудіо
  • provider:performAnswerCallAction — користувач відповів, потрібна активація AVAudioSession
  • provider:performEndCallAction — виклик завершено, потрібно зупинити медіа
  • provider:performSetMutedCallAction — перемикання мікрофона

Інтеграція PushKit з CallKit для вхідних викликів

PushKit — обов’язковий компонент для доставки вхідних VoIP-викликів у CallKit. Звичайні push-сповіщення (APNs) мають непередбачувану затримку і не гарантують доставку, якщо застосунок знаходиться у фоні. PushKit використовує постійне TCP-з’єднання з серверами Apple для миттєвої доставки VoIP-сповіщень, що критично важливо для дзвінків у реальному часі.

Схема роботи: сервер відправляє VoIP-сповіщення через PushKit → застосунок отримує його в pushRegistry:didReceiveIncomingPushWithPayload → застосунок негайно відображає вхідний виклик через CXProvider → CallKit показує системний екран виклику. Все відбувається за частки секунди, і користувач бачить дзвінок одночасно з його надходженням на сервер.

Починаючи з iOS 13, Apple ввела обмеження: VoIP-сповіщення повинні використовуватися тільки для індикації вхідних викликів. Використання PushKit для фонового завантаження даних або оновлення контенту заборонено — такі застосунки можуть бути відхилені при модерації. Ця зміна зробила екосистему VoIP більш передбачуваною, оскільки всі PushKit-сповіщення тепер гарантовано пов’язані з дзвінками.

Приклад обробки вхідного PushKit-сповіщення

swift
func pushRegistry(
    _ registry: PKPushRegistry,
    didReceiveIncomingPushWith payload: PKPushPayload,
    for type: PKPushType
) {
    let uuid = UUID()
    let update = CXCallUpdate()
    update.remoteHandle = CXHandle(
        type: .phoneNumber,
        value: payload.dictionaryPayload["caller"]
    )
    update.hasVideo = false
    
    provider.reportNewIncomingCall(with: uuid, update: update)
}

Call Directory Extension: блокування та ідентифікація номерів

Call Directory Extension — App Extension, яке дозволяє застосунку надавати системі списки номерів для ідентифікації (відображення імені того, хто дзвонить) та блокування. Розширення працює незалежно від основного застосунку: система завантажує дані з розширення при активації, і всі подальші операції виконуються без участі застосунку, що економить ресурси та підвищує безпеку.

Розширення використовує CXCallDirectoryManager для керування даними. Застосунок через основний процес додає номери в базу даних розширення, а потім викликає reloadExtension для оновлення системного кешу. Apple рекомендує оновлювати дані не частіше одного разу на годину, щоб уникнути зайвого навантаження на систему.

Приклад реалізації Call Directory Extension

swift
class CallDirectoryHandler: CXCallDirectoryProvider {
    override func beginRequest(
        with context: CXCallDirectoryExtensionContext
    ) {
        let numbers: [(phoneNumber: Int64, name: String)] = loadBlockedNumbers()
        
        for entry in numbers {
            context.addIdentificationEntry(
                withNextSequentialPhoneNumber: entry.phoneNumber,
                label: entry.name
            )
        }
        context.completeRequest()
    }
}
Метод CXCallDirectoryManagerПризначення
reloadExtensionПримусове оновлення кешу системи
getEnabledStatusПеревірка, чи ввімкнено розширення користувачем
openSettingsПерехід на екран налаштувань розширення

Приклад інтеграції CallKit на Swift

Повноцінна інтеграція CallKit вимагає налаштування трьох компонентів: конфігурації провайдера, обробки вхідних викликів через PushKit та керування аудіо-сесією. Нижче — мінімальний робочий приклад, який обробляє вхідний VoIP-виклик, відображає його через CallKit та активує аудіо.

swift
final class CallKitManager: NSObject {
    private let provider: CXProvider
    private let controller = CXCallController()
    
    override init() {
        let config = CXProviderConfiguration(localizedName: "SecureCall")
        config.supportedHandleTypes = [.phoneNumber]
        config.maximumCallGroups = 1
        self.provider = CXProvider(configuration: config)
        super.init()
        provider.setDelegate(self, queue: .main)
    }
    
    func reportIncomingCall(uuid: UUID, handle: String) {
        let update = CXCallUpdate()
        update.remoteHandle = CXHandle(type: .phoneNumber, value: handle)
        provider.reportNewIncomingCall(with: uuid, update: update)
    }
}

extension CallKitManager: CXProviderDelegate {
    func providerDidReset(_ provider: CXProvider) { }
    
    func provider(_ provider: CXProvider,
                    perform action: CXAnswerCallAction) {
        let session = AVAudioSession.sharedInstance()
        try? session.setCategory(.playAndRecord)
        try? session.setActive(true)
        action.fulfill()
    }
}

Обмеження та особливості CallKit на різних платформах

CallKit доступний на iOS, macOS та iPadOS, але поведінка фреймворку різниться між платформами. На iOS CallKit працює в повному обсязі: системний екран виклику, блокування екрану, інтеграція з CarPlay. На iPadOS відображення виклику відбувається у вигляді системного банера, а не повноекранного інтерфейсу. На macOS CallKit доступний з macOS 10.14 Mojave, але тільки для Mac-застосунків, зібраних з Catalyst або тих, що використовують AppKit безпосередньо.

Ключове обмеження — CallKit не підтримується на watchOS. Розробники Apple Watch не можуть відображати VoIP-виклики через системний інтерфейс на годиннику. Натомість watchOS застосунок отримує сповіщення про виклик через WCSession і повинен реалізувати власний екран дзвінка. Також CallKit не працює на симуляторі — тестування VoIP-функцій можливе тільки на фізичному пристрої.

Порівняння CallKit на iOS, iPadOS та macOS

ФункціяiOSiPadOSmacOS
Системний екран викликуПовноекраннийБанерБанер
Lock ScreenТакНіНі
CarPlayТакНіНі
Call DirectoryТакТакНі
Історія RecentsТакТакТак

Часті запитання

Чи обов’язково використовувати PushKit разом з CallKit?

Так, для вхідних викликів PushKit обов’язковий. Тільки PushKit гарантує миттєву доставку VoIP-сповіщення сплячому або закритому застосунку, що критично для своєчасного відображення дзвінка через CallKit.

Чи можна використовувати CallKit для відеодзвінків?

Так, CallKit підтримує аудіо та відео. При конфігурації CXProvider вкажіть supportsVideo = true, а в CXStartCallAction встановіть isVideo = true. Система коректно відобразить іконку відеокамери в інтерфейсі виклику.

Як тестувати CallKit без фізичного пристрою?

Ніяк — CallKit не працює на симуляторі. Для тестування використовуйте фізичний пристрій iOS або iPadOS. На macOS можна тестувати на реальному Mac з мікрофоном.

Чи можуть два застосунки одночасно використовувати CallKit?

Так, кожен застосунок реєструє свій CXProvider. Система коректно обробляє виклики від різних застосунків та відображає їх як окремі дзвінки в Recents. Користувач бачить, з якого застосунку надійшов виклик.

Що станеться, якщо не активувати AVAudioSession після відповіді на виклик?

CallKit автоматично завершить виклик через обмежений час, якщо застосунок не активує аудіо-сесію. Таймер спрацьовує, щоб система не залишалася в стані дзвінка без реального аудіопотоку.

Підсумки

  • CallKit — фреймворк Apple для інтеграції VoIP-дзвінків у системний застосунок Телефон на iOS, iPadOS та macOS, доступний з iOS 10.
  • CXProvider та CXCallController — основні класи архітектури CallKit, що реалізують патерн провайдер-клієнт для керування викликами.
  • PushKit — обов’язковий компаньйон CallKit для миттєвої доставки вхідних VoIP-сповіщень, що працює через постійне TCP-з’єднання.
  • Call Directory Extension дозволяє блокувати та ідентифікувати номери на системному рівні, що корисно для антиспам-застосунків.
  • CallKit не підтримується на watchOS і не працює на симуляторі — тестування VoIP-функцій вимагає фізичного пристрою.
  • На різних платформах поведінка CallKit різниться: на iOS — повноекранний інтерфейс, на iPadOS та macOS — системний банер.
  • Активація AVAudioSession після відповіді на виклик обов’язкова — без неї CallKit завершить дзвінок за таймаутом.

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також