Data Channel - iOS
The data channel sends text or binary data to all other participants in the room with low delay. Use it for live data that matters only at that moment, such as cursor positions, reactions, typing indicators or game moves.
Messages are not stored on the server. A participant who joins later does not receive the messages that were sent before they joined.
Data Channel or PubSub
Both send messages to other participants. Choose by what your messages need.
| Data channel | PubSub | |
|---|---|---|
| Who receives a message | All other participants | Participants subscribed to the topic. With sendOnly, only the participants you list. |
| Kept for participants who join later | No | Yes, when you publish with persist: true |
| Content | A String or Data, up to 15 KiB | A String message, with an optional payload dictionary |
| Unreliable delivery | Yes, with reliable: false | No |
Send a message
The send(_:reliable:) method of the Room class sends a String or Data to all other participants.
- It is
async throws. Call it withtry awaitinside aTask, after you join the room. reliable: true, the default, resends the message until it arrives, and messages arrive in the order you sent them.reliable: falsesends the message once. It can be lost or arrive out of order, so use it for data where a newer message replaces an older one, such as cursor positions.- A message can be at most 15 KiB. For text, this is the size of the string in UTF-8.
- Only participants in
SEND_AND_RECVmode can send.
import VideoSDKRTC
// The data this example sends as binary
struct CursorPosition: Codable {
let x: Double
let y: Double
}
extension RoomViewController {
// Send text, reliably and in order
@IBAction func sendHelloTapped(_ sender: Any) {
Task {
do {
try await room?.send("Hello everyone")
} catch let error as VideoSDKError {
print("Send failed: \(error.name) (\(error.code)): \(error.message)")
} catch {
print("Send failed: \(error)")
}
}
}
// Send binary data once. A newer position replaces a lost one.
func sendCursorPosition(x: Double, y: Double) {
Task {
do {
let data = try JSONEncoder().encode(CursorPosition(x: x, y: y))
try await room?.send(data, reliable: false)
} catch {
print("Send failed: \(error)")
}
}
}
}
Errors
When the message is not sent, send(_:reliable:) throws a VideoSDKError:
| Error | When |
|---|---|
ERROR_ACTION_PERFORMED_BEFORE_ROOM_JOINED (3035) | Before you join the room, or after you leave it. |
ERROR_ROOM_RECONNECTING (3065) | While the room is reconnecting. Send the message again after it reconnects. |
ERROR_ACTION_NOT_SUPPORTED_IN_MODE (3066) | In RECV_ONLY or SIGNALLING_ONLY mode. |
ERROR_PAYLOAD_TOO_LARGE (3072) | The message is larger than 15 KiB. |
ERROR_MEDIA_NOT_READY (3048) | The room's media connection is not ready. |
ERROR_OPERATION_TIMED_OUT (3079) | The data channel did not open in time. |
ERROR_SEND_FAILED (3070) | The data channel could not send the message. |
ERROR_ACTION_PERFORMED_BEFORE_ROOM_JOINED, ERROR_OPERATION_TIMED_OUT and ERROR_SEND_FAILED are also sent to onError(error:), so handle them in one place.
Receive messages
Implement onDataReceived(_:) of RoomEventListener. It is called on the main thread for every message that another participant sends. You do not receive your own messages.
The DataMessage it receives has these properties:
senderId: The ID of the participant who sent the message.text: The text, ornilwhen the sender sentData.data: The binary data, ornilwhen the sender sent text.isBinary:truewhen the content is indata.reliable:truewhen the sender sent it reliably,falsewhen the sender usedreliable: false.timestamp: When the message arrived on this device, in milliseconds since 1970. It is not the time it was sent.
import VideoSDKRTC
extension RoomViewController: RoomEventListener {
func onDataReceived(_ data: DataMessage) {
if data.isBinary {
guard let bytes = data.data,
let position = try? JSONDecoder().decode(CursorPosition.self, from: bytes) else { return }
print("\(data.senderId) moved the cursor to \(position.x), \(position.y)")
} else {
print("\(data.senderId): \(data.text ?? "")")
}
}
}
Add the listener to the room with room?.addEventListener(self), for example right after createRoom().
API Reference
The API references for all the methods and events utilized in this guide are provided below.
Got a Question? Ask us on discord

