Skip to main content
Version: 4.x.x

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 channelPubSub
Who receives a messageAll other participantsParticipants subscribed to the topic. With sendOnly, only the participants you list.
Kept for participants who join laterNoYes, when you publish with persist: true
ContentA String or Data, up to 15 KiBA String message, with an optional payload dictionary
Unreliable deliveryYes, with reliable: falseNo

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 with try await inside a Task, 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: false sends 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_RECV mode 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:

ErrorWhen
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, or nil when the sender sent Data.
  • data: The binary data, or nil when the sender sent text.
  • isBinary: true when the content is in data.
  • reliable: true when the sender sent it reliably, false when the sender used reliable: 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