Documentation Index
Fetch the complete documentation index at: https://mintlify.com/livekit/client-sdk-swift/llms.txt
Use this file to discover all available pages before exploring further.
LiveKit allows participants to send arbitrary data to other participants in the room using data channels. This is useful for sending text messages, custom signaling, or any application-specific data.
Publishing Data
Send data to other participants using the publish(data:options:) method:
let message = "Hello, world!"
let data = message.data(using: .utf8)!
try await room.localParticipant.publish(data: data)
Data Publish Options
Control delivery behavior using DataPublishOptions:
let options = DataPublishOptions(
reliable: true, // Use reliable data channel
destinationIdentities: [], // Send to specific participants (empty = all)
topic: "chat" // Optional topic/channel identifier
)
try await room.localParticipant.publish(data: data, options: options)
Options:
reliable: When true, uses TCP-like reliable delivery. When false, uses UDP-like lossy delivery for lower latency
destinationIdentities: Array of participant identities to receive the data. Empty array sends to all participants
topic: Optional string to categorize messages (useful for filtering on the receiving end)
Reliable vs. Lossy Delivery
Best for: Chat messages, file transfers, critical datalet options = DataPublishOptions(reliable: true)
try await room.localParticipant.publish(data: data, options: options)
- Guarantees delivery and order
- Higher latency under poor network conditions
- Uses TCP-like transmission
Best for: Game state updates, real-time coordinates, non-critical datalet options = DataPublishOptions(reliable: false)
try await room.localParticipant.publish(data: data, options: options)
- No delivery guarantee
- Lower latency
- Uses UDP-like transmission
Receiving Data
Implement the RoomDelegate protocol to receive data messages:
class MyRoomDelegate: RoomDelegate {
func room(
_ room: Room,
participant: RemoteParticipant?,
didReceiveData data: Data,
topic: String?
) {
// Handle received data
if let message = String(data: data, encoding: .utf8) {
print("Received message: \(message)")
print("From participant: \(participant?.identity ?? "unknown")")
print("Topic: \(topic ?? "none")")
}
}
}
// Add delegate to room
room.add(delegate: MyRoomDelegate())
Filtering by Topic
Use topics to organize different types of data messages:
func room(
_ room: Room,
participant: RemoteParticipant?,
didReceiveData data: Data,
topic: String?
) {
switch topic {
case "chat":
handleChatMessage(data, from: participant)
case "game-state":
handleGameState(data)
case "reaction":
handleReaction(data, from: participant)
default:
print("Unknown topic: \(topic ?? "none")")
}
}
Sending to Specific Participants
Send data to one or more specific participants:
// Send to a single participant
let targetIdentity = Participant.Identity("user123")
let options = DataPublishOptions(
reliable: true,
destinationIdentities: [targetIdentity]
)
try await room.localParticipant.publish(data: data, options: options)
// Send to multiple participants
let identities = [
Participant.Identity("user123"),
Participant.Identity("user456")
]
let options = DataPublishOptions(
reliable: true,
destinationIdentities: identities
)
try await room.localParticipant.publish(data: data, options: options)
Size Limits
Each data payload must not exceed 15KB. For larger data:
func sendLargeData(_ data: Data) async throws {
let chunkSize = 15_000 // 15KB
let chunks = stride(from: 0, to: data.count, by: chunkSize).map {
data[$0..<min($0 + chunkSize, data.count)]
}
for (index, chunk) in chunks.enumerated() {
let metadata = "chunk-\(index)-of-\(chunks.count)"
try await room.localParticipant.publish(
data: chunk,
options: DataPublishOptions(
reliable: true,
topic: metadata
)
)
}
}
Setting Default Options
Set default data publish options when creating a room:
let roomOptions = RoomOptions(
defaultDataPublishOptions: DataPublishOptions(
reliable: true,
topic: "default"
)
)
let room = Room(roomOptions: roomOptions)
// This will use the default options
try await room.localParticipant.publish(data: data)
Use Cases
Chat Messages
struct ChatMessage: Codable {
let text: String
let timestamp: Date
}
func sendChatMessage(_ text: String) async throws {
let message = ChatMessage(text: text, timestamp: Date())
let data = try JSONEncoder().encode(message)
try await room.localParticipant.publish(
data: data,
options: DataPublishOptions(
reliable: true,
topic: "chat"
)
)
}
Real-time Cursor Position
struct CursorPosition: Codable {
let x: Double
let y: Double
}
func sendCursorPosition(_ position: CursorPosition) async throws {
let data = try JSONEncoder().encode(position)
try await room.localParticipant.publish(
data: data,
options: DataPublishOptions(
reliable: false, // Low latency, lossy OK
topic: "cursor"
)
)
}
Reactions
func sendReaction(_ emoji: String) async throws {
let data = emoji.data(using: .utf8)!
try await room.localParticipant.publish(
data: data,
options: DataPublishOptions(
reliable: true,
topic: "reaction"
)
)
}
Error Handling
Handle errors when publishing data:
do {
try await room.localParticipant.publish(data: data)
} catch {
print("Failed to publish data: \(error)")
if let lkError = error as? LiveKitError {
switch lkError.type {
case .invalidState:
print("Data channel is not open")
default:
print("Other error: \(lkError)")
}
}
}
See Also
- LocalParticipant.swift:117 (
publish(data:options:))
- Core/DataChannelPair.swift