LiveCommunicationKit is the modern replacement for CXProvider that delivers rich, native conversation UIs integrated with the Lock Screen, Dynamic Island, Phone app Recents, and Siri. It provides a unified lifecycle model for audio and video conversations with a single delegate-driven action pipeline.
⢠Replaces the aging CallKit/CXProvider API with a more flexible framework that supports audio, video, group conversations, hold/resume, and merging out of the box
⢠Conversations automatically appear full-screen on the Lock Screen with contact photo/name matching, in the Dynamic Island during multitasking, and in Phone app Recents ā with zero extra UI code
⢠A single perform-action delegate callback handles every interaction (system UI tap, in-app button, Siri command), eliminating duplicated state management and sync bugs
Shows how to create a ConversationManager, decode a PushKit payload, report an incoming conversation, and handle the JoinConversationAction in the single delegate callback.
import LiveCommunicationKit
import PushKit
import UIKit
// MARK: - App-level manager created at launch
final class ConversationCoordinator: NSObject {
static let shared = ConversationCoordinator()
let manager: ConversationManager
private override init() {
let config = ConversationManager.Configuration(
localizedName: "FriendChat",
ringtoneSound: .init(named: "ringtone"),
iconImage: UIImage(named: "AppIcon"),
maximumGroups: 2,
maximumConversationsPerGroup: 5,
includesConversationsInRecents: true,
supportsVideo: false,
supportedHandleTypes: [.phoneNumber]
)
manager = ConversationManager(configuration: config)
super.init()
manager.delegate = self
}
}
// MARK: - PushKit integration
extension ConversationCoordinator: PKPushRegistryDelegate {
func pushRegistry(
_ registry: PKPushRegistry,
didReceiveIncomingPushWith payload: PKPushPayload,
for type: PKPushType,
completion: @escaping () -> Void
) {
guard type == .voIP else { completion(); return }
let dict = payload.dictionaryPayload
guard
let uuidString = dict["uuid"] as? String,
let uuid = UUID(uuidString: uuidString),
let phoneNumber = dict["caller"] as? String
else { completion(); return }
let handle = Conversation.Handle(
kind: .phoneNumber,
value: phoneNumber,
displayName: "Unknown Caller"
)
let update = Conversation.Update(
handles: [handle],
capabilities: [.video, .pausing]
)
// Must be called before this method returns
manager.reportIncomingConversation(uuid: uuid, update: update)
completion()
}
func pushRegistry(_ registry: PKPushRegistry,
didUpdate credentials: PKPushCredentials,
for type: PKPushType) {}
}
// MARK: - Conversation lifecycle handling
extension ConversationCoordinator: ConversationManagerDelegate {
func conversationManager(
_ manager: ConversationManager,
perform action: ConversationAction
) {
switch action {
case let join as JoinConversationAction:
handleJoin(join)
case let end as EndConversationAction:
handleEnd(end)
default:
action.fail()
}
}
private func handleJoin(_ action: JoinConversationAction) {
guard manager.conversations.contains(where: { $0.uuid == action.uuid }) else {
action.fail(); return
}
manager.reportConversationConnecting(uuid: action.uuid)
Task {
do {
try await MediaStreamService.shared.connect(conversationID: action.uuid)
manager.reportConversationConnected(uuid: action.uuid)
action.fulfill()
} catch {
action.fail()
}
}
}
private func handleEnd(_ action: EndConversationAction) {
manager.reportConversationLeaving(uuid: action.uuid)
Task {
await MediaStreamService.shared.disconnect(conversationID: action.uuid)
manager.reportConversationLeft(uuid: action.uuid)
action.fulfill()
}
}
}
// MARK: - Stub for compilation
final class MediaStreamService {
static let shared = MediaStreamService()
func connect(conversationID: UUID) async throws {}
func disconnect(conversationID: UUID) async {}
}iOS 27 adds sectioned queries, codable model attributes, ResultsObserver for non-SwiftUI change observation, and HistoryObserver for reacting to persistent history changes in SwiftData.
The NowPlaying framework introduces a first-class Swift API for surfacing app media in system-wide now-playing surfaces ā Lock Screen, Control Center, Dynamic Island, StandBy, CarPlay, Apple Watch, and Apple TV ā via a declarative MediaSessionRepresentable protocol. It also supports remote media sessions (for controlling external speakers/TVs) and Media Sharing Extensions for routing media to third-party devices.
USDKit is a new first-party Swift framework introduced in iOS/macOS 27 that brings native USD scene creation, composition, modification, and export capabilities to Apple platform apps, with deep RealityKit and Spatial Preview integration.
Apps must report the incoming conversation before the PKPushRegistryDelegate method returns or the system will terminate the app. The ConversationManager should be created at app launch, not lazily, to avoid missing early actions. CXProvider-based apps should migrate ā both cannot be active simultaneously for the same app.
Requires VoIP background mode entitlement and PushKit registration; full Lock Screen and Dynamic Island integration requires physical device
iOS 27 expands the App Intents framework with RelevantEntities for contextual content surfacing, EntityCollection for high-performance batch parameter handling, SyncableEntity for cross-device Siri continuity, native Duration/PersonNameComponents parameter types, and @UnionValue for multi-type parameters ā plus extended intent execution time limits.