Skip to main content
Version: 3.x.x

PubSub - iOS

PubSub is a short acronym for Publish-Subscribe mechanism. This mechanism is used to send and recieve messages from a particular topic. As the name suggests, for someone to send a message, they have to specify the topic and the message which should be published and for someone to receive a message, they should be subscribed to that topic.

Here is a visual to better understand publish-subscribe mechanism.

pubsub

pubSub

In order to use PubSub in meeting, VideoSDK provides a class pubSub which allows you to subscribe to any topic and publish to any topic allowing to pass on messages and instructions during the meeting easily.

publish()

  • This method is used for publishing message of specific topic.
  • This method can be accessed from the pubSub class, which is subclass of Meeting class.
  • This method will accept following parameters as input:
    • topic: This will be the topic for which you are publishing a message.
    • message: This will be the actual message to be published. It has to be in String format.
    • options: This is an object of PubSubPublishOptions which specifies the options for publish. PubSubPublishOptions has 2 properties.
      • persist : persist offered the option of keeping the message around for the duration of the session. When persist is set to true, that message will be retained for upcoming participants and will be available in VideoSDK Session Dashboard with .CSV format after completion of session.
      • sendOnly: If you want to send a message to specific participants, you can pass their respective participantId in form of String[]. If you don't provide any IDs or pass a null value, the message will be sent to all participants by default. This is optional parameter.
  //Button that will send the message when tapped
@IBAction func sendMessageTapped(_ sender: Any) {
let options = ["persist" : true]
// publish message
Task {
do {
try await self.meeting?.pubsub.publish(topic: "CHAT", message: "How are you?", options: options)
} catch {
print("error while publish: \(error)")
}
}
}

subscribe()

  • This method is used to subscribe for particular topic.

  • meeting.pubsub.subscribe(topic, forListener, options?) accepts a listener and an optional options object. It is async throws. All messages — realtime and old — are delivered exclusively through the listener callbacks; nothing is returned from the awaited call.

  • This method will accept following parameters as input:

    • topic: This will be the topic to be subscribed.

    • listener: This is an object of PubSubMessageListener containing listener callbacks:

      • onMessageReceived(message) — Called for every realtime message as soon as it is received.

        • Use this when: You want to handle each message individually, such as appending it to a chat, triggering a notification, or updating message-specific state.
        • Don't use this when: The topic is high-throughput / large-scale (busy chats, live reactions, cursor positions). Firing once per message causes excessive re-renders and state updates — use onBatchReceived instead.
      • onBatchReceived(messages) — Called with an array of realtime messages. These are the same messages delivered through onMessageReceived, but grouped into a single batch.

        • Use this when: Processing messages in bulk is more efficient, such as performing a single state update or rendering a large list of messages.
      • onOldMessagesReceived(messages, info) — Called with persisted history in batches — fires once per batch until history is fully delivered. Only messages published with persist: true are delivered here. info.isLast is true on the final batch.

        • Use this when: Loading chat history or restoring previously sent messages when a participant joins the meeting.
      • onMessageDrop(info) — Called when incoming realtime messages cannot be delivered. This can happen:

        • because the client cannot keep up with the incoming message rate (for example, due to a slow network or high CPU usage), causing overflow, or
        • because newMessageLimit is configured, which intentionally limits how many realtime messages are delivered every 500 ms. Any messages exceeding the configured limit within that window are discarded.

        info.droppedCount contains the number of messages that were not delivered.

        • Use this when: Notifying users that some realtime messages were missed, monitoring the effects of newMessageLimit, or logging dropped messages for debugging and observability.
    • options: This is an object of PubSubSubscribeOptions, which has below properties:

      • oldMessageLimit (number) — how many old messages to receive. Pass 0 to receive none. If omitted, all old messages are delivered. Default: all.

        • When to use: Cap the history for large sessions where loading every persisted message would be wasteful (e.g. only the last 50 messages need to appear when a participant joins).
      • realtimeOverflow (RealtimeOverflow Enum) — behavior when your internet is slow or your device can't keep up. RealtimeOverflow.queue (default) queues remaining messages so you receive them once you catch up; RealtimeOverflow.drop drops them instead.

        • When to use: Use RealtimeOverflow.queue for chat where every message matters. Use RealtimeOverflow.drop for high-frequency, low-value streams (live reactions, cursor positions) where stale data is worse than missing data.
      • maxQueue (number) — maximum number of message batches to queue during overflow. Default: 70. Max: 200. Only valid with realtimeOverflow: .queue.

        • When to use: Increase this value when you want to retain more messages and catch up after recovering from a slow network or CPU spike. Lower it if memory pressure matters more than history.
      • newMessageLimit (number) — maximum number of realtime messages to receive per 500 ms.

        • When to use: Set this when you want to render only a particular number of messages per second — for example, throttle a busy chat topic so the UI doesn't jank, or rate-limit a reactions topic.
note

If you call subscribe() again on the same topic with a different listener, the values of realtimeOverflow, maxQueue, and newMessageLimit are overridden by the latest subscribe() call. Other options (such as oldMessageLimit) are not affected.

Every message delivered to the listener contains the following fields:

  • id — unique identifier for the message.
  • message — the actual message content that was sent.
  • senderIdparticipantId of the participant who sent the message.
  • senderNamedisplayName of the participant who sent the message.
  • timestamp — the timestamp indicating when the message was published.
  • topic — the topic the message was published to.
  • payload — any additional data sent along with the message (optional).
extension MeetingViewController: MeetingEventListener {

/// Meeting started
func onMeetingJoined() {
Task {
var demoOptions = PubSubSubscribeOptions()
demoOptions.oldMessageLimit = 50
demoOptions.realtimeOverflow = .queue
demoOptions.maxQueue = 70
demoOptions.newMessageLimit = 20

do {
try await meeting?.pubsub.subscribe(
topic: "CHAT",
forListener: self,
options: demoOptions
)
} catch {
print("\(topic) subscribe failed: \(error.localizedDescription)")
}
}
}
}

extension MeetingViewController: PubSubMessageListener {
// read message when it is received
func onMessageReceived(_ message: PubSubMessage) {
print("Message Received: " + message.message)
}

func onBatchReceived(_ messages: [VideoSDKRTC.PubSubMessage]) {
// Handle a batch of realtime messages together
print("Batch messages: \(messages.count)")
}

func onOldMessagesReceived(_ messages: [VideoSDKRTC.PubSubMessage], info: PubSubHistoryInfo) {
print("onOldMessagesReceived: \(messages.count) | isLast: \(info.isLast)")
}

func onMessageDrop(_ info: PubSubMessageDropInfo) {
// Called when incoming messages are dropped
print("\(info.droppedCount) message(s) dropped")
}
}

unsubscribe()

  • This method is used to unsubscribe for particular topic.

  • This method will accept two parameters as input:

    • topic: This will be the topic to be unsubscribed.
    • listener: This is an object of PubSubMessageListener, which was passed in subscribe().
func unsubscribe() {
//unsubscribe to the topic 'CHAT' when onMeetingLeft is triggered
Task {
do {
try await self.meeting?.pubsub.unsubscribe(topic: "CHAT", forListener: self)
} catch {
print("unsubscribe failed: \(error)")
}
}
}

Errors

All PubSub methods are async throws and fail with the typed PubSubError enum, so you can switch over the specific case in a catch block. Cases that carry a String hold the underlying reason returned by the server.

publish() throws:

  • .meetingNotJoined — the operation was attempted before the meeting was joined (or after it left).
  • .meetingReconnecting — the meeting is reconnecting. Retry once it reconnects.
  • .operationTimeout — the PubSub socket is disconnected or closed, so the operation cannot proceed.
  • .publishFailed(String) — the publish failed.

subscribe() throws:

  • .invalidOldMessageLimit(Int)oldMessageLimit is negative. It must be nil or >= 0.
  • .invalidMaxQueue(Int)maxQueue is less than 1.
  • .invalidNewMessageLimit(Int)newMessageLimit is negative. It must be >= 0.
  • .maxQueueNotAllowedWithDropmaxQueue was set while realtimeOverflow is .drop. It is only valid with .queue.
  • .alreadySubscribed — this listener is already subscribed to the topic. Ensure that one listener is subscribed at most ones per topic — unsubscribe() first if you need to re-subscribe. If you need to listen the events at differnet places, use and create another listener and call subscribe() with it.
  • .meetingNotJoined — the operation was attempted before the meeting was joined (or after it left).
  • .meetingReconnecting — the meeting is reconnecting. Retry once it reconnects.
  • .operationTimeout — the PubSub socket is disconnected or closed.
  • .subscribeFailed(String) — the subscribe failed.

unsubscribe() throws:

  • .unsubscribeFailed — unsubscribe request failed.

Applications of usePubSub

PubSub is a very powerful mechanism which can be used to do alot of things which can make your meeting experience much more interactive. Some of the most common usecase that we have come across for the PubSub during a meeting are listed below:

  1. Chat: You can utilise this to develop various Chat features, such as Private Chat and Group Chat. You can follow our chat integration guide here.
  2. Raise Hand: You can allow attendees to raise their hands at any time during the meeting, informing everyone else that someone has done so.
  3. Poll: You may make polls, let users respond to them, and display the results at the end of a poll.
  4. Question Answer Session: You can also design interactive functionality that is question-and-answer based.

Downloading PubSub Messages

All the messages from the PubSub which were published with persist : true and can be downloaded as an .csv file. This file will be available in the VideoSDK dashboard as well as throught the Sessions API.

API Reference

The API references for all the methods and events utilised in this guide are provided below.

Got a Question? Ask us on discord