-
Créez des expériences de communication en temps réel
LiveCommunicationKit transforme vos apps de communication en temps réel en expériences intégrées. Nous vous montrons comment offrir une interface de conversation native et riche qui place votre app exactement là où les utilisateurs en ont besoin : de la présentation en plein écran sur l'écran verrouillé à une expérience multitâche fluide avec Dynamic Island. Rejoignez-nous pour découvrir l'intégration étape par étape du framework pour les conversations entrantes, sortantes et de groupe.
Chapitres
- 0:01 - Introduction
- 7:56 - Incoming conversations
- 11:29 - Outgoing conversations
- 13:18 - Groups
Ressources
- Initiating VoIP conversations with LiveCommunicationKit
- Responding to VoIP Notifications from PushKit
- LiveCommunicationKit
Vidéos connexes
WWDC25
WWDC22
-
Rechercher dans cette vidéo…
-
-
6:41 - Set up a conversation manager
// Set up a conversation manager import LiveCommunicationKit let configuration = ConversationManager.Configuration( ringtoneName: "SampleRingtone.caf", iconTemplateImageData: UIImage(named: "SampleIcon")?.pngData(), maximumConversationGroups: 1, maximumConversationsPerConversationGroup: 2, includesConversationInRecents: true, supportsVideo: true, supportedHandleTypes: [.phoneNumber, .emailAddress] ) let manager = ConversationManager(configuration: configuration) manager.delegate = self -
9:22 - Report the incoming conversation to the system
// Report the incoming conversation to the system import LiveCommunicationKit import PushKit final class SamplePushHandler: NSObject, PKPushRegistryDelegate { func pushRegistry( _ registry: PKPushRegistry, didReceiveIncomingVoIPPushWith payload: PKPushPayload, metadata: PKVoIPPushMetadata) async { guard let (handle, uuid) = parseConversationPayload(from: payload) else { return } let capabilities = [.video, .pausing, .merging] let update = Conversation.Update(members: [handle], capabilities: capabilities) try? await manager.reportNewIncomingConversation(uuid: uuid, update: update) } } -
9:57 - Implement the delegate
// Implement the delegate import LiveCommunicationKit final class SampleDelegate: ConversationManagerDelegate { func conversationManager( _ manager: ConversationManager, perform action: ConversationAction ) { switch action { case let action as JoinConversationAction: handleJoinAction(action) default: action.fail() } } } -
10:13 - Fulfill the join action
// Handle a failed connection extension SampleDelegate { func handleJoinAction(_ action: JoinConversationAction) { guard let conversation = manager.conversations.first(where: {$0.uuid == uuid })else { return action.fail() } manager.reportConversationEvent(.conversationStartedConnecting(.now), for: conversation) Task { do { try await setupMediaStream(with: action.conversationUUID) manager.reportConversationEvent(.conversationConnected(.now), for: conversation) action.fulfill(dateConnected: .now) } catch { action.fail() } } } } -
11:17 - Route end actions
// Route end actions final class SampleDelegate: ConversationManagerDelegate { // … func conversationManager( _ manager: ConversationManager, perform action: ConversationAction ) { switch action { case let action as JoinConversationAction: handleJoinAction(action) case let action as EndConversationAction: handleEndAction(action) default: action.fail() } } } -
12:14 - Create a start action
let startAction = StartConversationAction( conversationUUID: UUID(), handles: [Handle(type: .phoneNumber, value: "+1-650-555-0199", displayName: "Ryan Notch")], isVideo: false ) -
12:23 - Perform the action
try await manager.perform([startAction]) -
12:29 - Route start actions
// Route start actions final class SampleDelegate: ConversationManagerDelegate { // … func conversationManager( _ manager: ConversationManager, perform action: ConversationAction ) { switch action { case let action as JoinConversationAction: handleJoinAction(action) case let action as EndConversationAction: handleEndAction(action) case let action as StartConversationAction: handleStartAction(action) default: action.fail() } } } -
13:51 - Start group conversations
// Start group conversations let adam = Handle(type: .emailAddress, value: "adam.halwani@icloud.com", displayName: "Adam Halwani") let david = Handle(type: .emailAddress, value: "david@example.com", displayName: "David Evans") let ryan = Handle(type: .phoneNumber, value: "+16505550199", displayName: "Ryan Notch") let startAction = StartConversationAction( conversationUUID: UUID(), handles: [david, ryan], isVideo: false ) try await manager.perform([startAction]) -
14:01 - Report group membership updates
// Report group membership updates let update = Conversation.Update( localMember: adam, members: [david, ryan], activeRemoteMembers: [david, ryan], capabilities: [.merging, .pausing, .unmerging] ) manager.reportConversationEvent( .conversationUpdated(update), for: conversation ) -
15:26 - Route merge actions
// Route merge actions final class SampleDelegate: ConversationManagerDelegate { func conversationManager( _ manager: ConversationManager, perform action: ConversationAction ) { switch action { case let action as JoinConversationAction: handleJoinAction(action) case let action as EndConversationAction: handleEndAction(action) case let action as StartConversationAction: handleStartAction(action) case let action as MergeConversationAction: handleMergeAction(action) default: action.fail() } } } -
15:33 - Handle the merge action
// Handle the merge action extension SampleDelegate { func handleMergeAction(_ action: MergeConversationAction) { let sourceUUID = action.conversationUUID let targetUUID = action.conversationUUIDToMergeWith guard manager.conversations.contains(where: { $0.uuid == sourceUUID }), manager.conversations.contains(where: { $0.uuid == targetUUID }) else { return action.fail() } Task { do { let update = try await combineStreams(from: sourceUUID, into: targetUUID) manager.reportConversationEvent(.conversationUpdated(update), for: target) action.fulfill() } catch { action.fail() } } } }
-
-
- 0:01 - Introduction
LiveCommunicationKit is the modern way to build live conversation experiences that integrate with the system. Conversations in LiveCommunicationKit are built upon fundamental elements, such as handles, display names, and capabilities, that configure the interface, as well as a single ConversationManager object to manage the full lifecycle.
- 7:56 - Incoming conversations
Incoming conversations rely on the ConversationManager class where you configure properties like ringtones, group limits, and supported handles. Use PushKit to deliver an incoming conversation to a device, then report it to the ConversationManager.
- 11:29 - Outgoing conversations
Start outgoing conversations initiated within the app by performing a StartConversationAction. This allows your app's ConversationManager delegate to handle the entire process, using the same unified action-handling logic for actions started by in-app or system UI.
- 13:18 - Groups
Track the full list of invited members in addition to the currently active remote members so the interface stays perfectly in sync as people join or drop off. Advanced call management is handled through delegate actions and supports merging and unmerging calls as needed.