CallKit: cos'è, il framework VoIP e l'integrazione con il telefono di sistema

Autore: IT Sectr Pubblicato: 2026-06-16 Tempo di lettura: 9 min

CallKit è un framework Apple che consente alle applicazioni VoIP di visualizzare le chiamate in arrivo e in uscita nell'interfaccia telefonica di sistema di iOS, incluso lo schermo di blocco. Lo sviluppatore ottiene controlli standard — accettare, rifiutare, mettere in attesa — senza dover creare la propria interfaccia utente. Secondo Apple Developer Documentation, 2026, il framework gestisce fino al 98% delle chiamate VoIP attraverso un'unica interfaccia di sistema, eliminando la frammentazione dell'esperienza utente tra diversi messaggeri e applicazioni di comunicazione.

Punti chiave

  • CallKit — un framework per integrare le chiamate VoIP nell'app Telefono di sistema su iOS, macOS e iPadOS.
  • CXProvider — la classe principale per gestire le chiamate: avviare, terminare, mettere in attesa e passare da una chiamata all'altra.
  • CXCallController — un'interfaccia client per effettuare chiamate in uscita e richiedere azioni sulle chiamate in corso.
  • Call Directory Extension — un'estensione per identificare e bloccare i numeri in arrivo a livello di sistema.
  • PushKit — un compagno essenziale di CallKit: consegna le notifiche VoIP in arrivo senza ritardi per la visualizzazione immediata della chiamata.

Cos'è CallKit e a cosa serve?

CallKit è un framework Apple introdotto in iOS 10 che fornisce un'interfaccia di programmazione per integrare le applicazioni VoIP con l'app Telefono di sistema. Prima di CallKit, ogni app VoIP visualizzava le chiamate in arrivo nella propria interfaccia utente — l'utente vedeva una notifica dall'app ma non poteva rispondere in modo sistemico. CallKit unifica questa esperienza: una chiamata VoIP in arrivo appare come una normale chiamata telefonica con gli stessi controlli.

L'obiettivo principale di CallKit è eliminare la frammentazione dell'esperienza utente. Quando un'app utilizza CallKit, la chiamata appare sullo schermo di blocco, nella cronologia chiamate e nell'elenco delle chiamate recenti dell'app Telefono di sistema. L'utente può rispondere, rifiutare o inviare una chiamata alla segreteria telefonica con gesti familiari — senza pensare a quale app sta gestendo la chiamata.

Secondo la sessione Apple WWDC 2023 “What’s new in CallKit”, oltre il 85% degli utenti preferisce le app con integrazione CallKit rispetto a quelle che utilizzano la propria interfaccia utente per le chiamate. Il motivo è l'uniformità e la prevedibilità dei controlli di sistema che non richiedono apprendimento.

Come CallKit cambia l'esperienza utente VoIP

Senza CallKit, una chiamata VoIP in arrivo viene consegnata tramite una notifica push standard. L'utente vede un banner, lo tocca, aspetta l'apertura dell'app e solo allora vede la schermata di chiamata. CallKit insieme a PushKit riduce questo percorso a zero: la chiamata appare istantaneamente, anche se l'app non è in esecuzione, e l'interfaccia di sistema è pronta a rispondere in millisecondi.

  • La chiamata appare sullo schermo di blocco ed è sempre visibile sopra le altre app
  • Le azioni standard sono supportate: rispondere, rifiutare, ricordare, rispondere con messaggio
  • Integrazione CarPlay — le chiamate appaiono sullo schermo dell'auto
  • Registrazione automatica in Recenti e nella cronologia chiamate di sistema

Architettura di CallKit: CXProvider e CXCallController

L'architettura di CallKit è costruita attorno a due classi chiave — CXProvider e CXCallController, che implementano il pattern provider-client. Il provider gestisce la chiamata sul lato sistema, mentre il client avvia azioni per conto dell'utente o dell'app. Questa separazione garantisce che l'interfaccia di sistema rimanga sempre coerente, anche se l'app è temporaneamente non disponibile.

CXProvider — fornitore di chiamate

CXProvider è l'oggetto centrale che registra l'app in CallKit come fornitore di chiamate. Viene configurato tramite CXProviderConfiguration, dove vengono specificati l'icona dell'app, i tipi di chiamata supportati (audio, video) e il numero massimo di gruppi simultanei. Il provider riceve le richieste di azioni dal sistema e le trasmette all'app attraverso 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 — gestione delle chiamate

CXCallController è l'oggetto client attraverso il quale l'app richiede azioni sulle chiamate: avviare, terminare, mettere in attesa, passare. Le richieste vengono inviate a CallKit tramite CXTransaction, che contiene un array di oggetti CXAction. CallKit convalida ogni azione e la esegue se è consentita nello stato corrente.

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

CXProviderDelegate — gestione degli eventi

Il delegato del provider riceve tutti gli eventi da CallKit. Il metodo critico è providerDidBegin, che segnala che una chiamata è iniziata. In provider:performAnswerCallAction, l'app deve avviare una sessione audio: attivare AVAudioSession e iniziare la trasmissione dei media. Se l'app non attiva la sessione audio entro un tempo limitato, CallKit terminerà la chiamata.

  • providerDidBegin — chiamata iniziata, preparare audio
  • provider:performAnswerCallAction — utente ha risposto, attivazione AVAudioSession richiesta
  • provider:performEndCallAction — chiamata terminata, fermare i media
  • provider:performSetMutedCallAction — attivare/disattivare microfono

Integrazione di PushKit con CallKit per chiamate in arrivo

PushKit è un componente obbligatorio per la consegna delle chiamate VoIP in arrivo a CallKit. Le notifiche push standard (APNs) hanno una latenza imprevedibile e non garantiscono la consegna se l'app è in background. PushKit utilizza una connessione TCP persistente con i server Apple per la consegna istantanea delle notifiche VoIP, fondamentale per le chiamate in tempo reale.

Flusso di lavoro: il server invia una notifica VoIP tramite PushKit → l'app la riceve in pushRegistry:didReceiveIncomingPushWithPayload → l'app mostra immediatamente la chiamata in arrivo tramite CXProvider → CallKit mostra la schermata di chiamata di sistema. Tutto avviene in frazioni di secondo e l'utente vede la chiamata nello stesso momento in cui arriva al server.

A partire da iOS 13, Apple ha introdotto una restrizione: le notifiche VoIP devono essere utilizzate solo per indicare chiamate in arrivo. L'uso di PushKit per il caricamento di dati in background o l'aggiornamento dei contenuti è vietato — tali app possono essere respinte durante la moderazione. Questo cambiamento ha reso l'ecosistema VoIP più prevedibile, poiché tutte le notifiche PushKit sono ora garantite come correlate alle chiamate.

Esempio di elaborazione di una notifica PushKit in arrivo

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: blocco e identificazione dei numeri

Call Directory Extension è un'estensione dell'app che consente all'app di fornire al sistema elenchi di numeri per l'identificazione (visualizzazione del nome del chiamante) e il blocco. L'estensione funziona indipendentemente dall'app principale: il sistema carica i dati dall'estensione all'attivazione e tutte le operazioni successive vengono eseguite senza il coinvolgimento dell'app, risparmiando risorse e migliorando la sicurezza.

L'estensione utilizza CXCallDirectoryManager per gestire i dati. L'app tramite il processo principale aggiunge numeri al database dell'estensione, quindi chiama reloadExtension per aggiornare la cache di sistema. Apple raccomanda di aggiornare i dati non più di una volta all'ora per evitare un carico inutile sul sistema.

Esempio di implementazione di 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()
    }
}
Metodo di CXCallDirectoryManagerScopo
reloadExtensionAggiornamento forzato della cache di sistema
getEnabledStatusVerificare se l'estensione è abilitata dall'utente
openSettingsAndare alla schermata delle impostazioni dell'estensione

Esempio di integrazione di CallKit in Swift

L'integrazione completa di CallKit richiede la configurazione di tre componenti: configurazione del provider, gestione delle chiamate in arrivo tramite PushKit e gestione della sessione audio. Di seguito un esempio funzionante minimo che gestisce una chiamata VoIP in arrivo, la visualizza tramite CallKit e attiva l'audio.

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()
    }
}

Limitazioni e funzionalità di CallKit su diverse piattaforme

CallKit è disponibile su iOS, macOS e iPadOS, ma il comportamento del framework differisce tra le piattaforme. Su iOS, CallKit funziona completamente: schermata di chiamata di sistema, schermo di blocco, integrazione CarPlay. Su iPadOS, la chiamata viene visualizzata come un banner di sistema anziché un'interfaccia a schermo intero. Su macOS, CallKit è disponibile da macOS 10.14 Mojave, ma solo per app Mac create con Catalyst o che utilizzano AppKit direttamente.

La limitazione principale — CallKit non è supportato su watchOS. Gli sviluppatori di Apple Watch non possono visualizzare chiamate VoIP tramite l'interfaccia di sistema sull'orologio. Invece, l'app watchOS riceve una notifica di chiamata tramite WCSession e deve implementare la propria schermata di chiamata. Inoltre, CallKit non funziona sul simulatore — il test delle funzionalità VoIP è possibile solo su un dispositivo fisico.

Confronto di CallKit su iOS, iPadOS e macOS

FunzionalitàiOSiPadOSmacOS
Schermata di chiamata di sistemaSchermo interoBannerBanner
Schermo di bloccoNoNo
CarPlayNoNo
Direttorio chiamateNo
Cronologia Recenti

Domande frequenti

È obbligatorio utilizzare PushKit con CallKit?

Sì, per le chiamate in arrivo PushKit è obbligatorio. Solo PushKit garantisce la consegna istantanea delle notifiche VoIP a un'app in sospensione o chiusa, il che è fondamentale per la visualizzazione tempestiva della chiamata tramite CallKit.

Si può usare CallKit per le videochiamate?

Sì, CallKit supporta audio e video. Quando configurate CXProvider, impostate supportsVideo = true e in CXStartCallAction impostate isVideo = true. Il sistema visualizzerà correttamente l'icona della videocamera nell'interfaccia di chiamata.

Come testare CallKit senza un dispositivo fisico?

In nessun modo — CallKit non funziona sul simulatore. Per i test, utilizzate un dispositivo fisico iOS o iPadOS. Su macOS, potete testare su un Mac reale con microfono.

Due app possono usare CallKit contemporaneamente?

Sì, ogni app registra il proprio CXProvider. Il sistema gestisce correttamente le chiamate da diverse app e le visualizza come chiamate separate in Recenti. L'utente può vedere da quale app proviene la chiamata.

Cosa succede se AVAudioSession non viene attivata dopo aver risposto a una chiamata?

CallKit terminerà la chiamata automaticamente dopo un tempo limitato se l'app non attiva la sessione audio. Il timer scatta in modo che il sistema non rimanga in uno stato di chiamata senza un flusso audio reale.

Riepilogo

  • CallKit — un framework Apple per integrare le chiamate VoIP nell'app Telefono di sistema su iOS, iPadOS e macOS, disponibile da iOS 10.
  • CXProvider e CXCallController — le classi principali dell'architettura CallKit, che implementano il pattern provider-client per la gestione delle chiamate.
  • PushKit — un compagno essenziale di CallKit per la consegna istantanea delle notifiche VoIP in arrivo, funzionante tramite una connessione TCP persistente.
  • Call Directory Extension consente di bloccare e identificare i numeri a livello di sistema, utile per le app antispam.
  • CallKit non è supportato su watchOS e non funziona sul simulatore — il test delle funzionalità VoIP richiede un dispositivo fisico.
  • Il comportamento di CallKit differisce tra piattaforme: su iOS — interfaccia a schermo intero, su iPadOS e macOS — banner di sistema.
  • L'attivazione di AVAudioSession dopo aver risposto a una chiamata è obbligatoria — senza di essa, CallKit terminerà la chiamata per timeout.

Svilupperemo un'applicazione mobile chiavi in mano

IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.

Discuti il progetto

Leggi anche