Skip to main content

Registering and unregistering

All meeting events are reported through SMeetingDelegate:
Key points:
  • delegates is a weak-reference multicast, so you can register multiple observers; the SDK doesn’t extend your object’s lifetime because you registered it
  • Every method in the protocol has a default empty implementation, so you only implement the events you care about
  • Call meeting.delegates.remove(delegate:) when you no longer need it
  • Callbacks are always dispatched on the main thread, so you can update the UI directly
If your observer is a @MainActor type, declare the protocol methods as nonisolated, then hop back to the main actor context inside them:

Connection events

The reason of DisconnectEventData is a DisconnectReason, which tells you whether you exited on your own or were disconnected; error carries the underlying error when the disconnection is abnormal.

Member events

When byAdmin in a media state event is true, the change was caused by a host action, and opUid is the operator. You can use this to show the user a hint such as “The host turned off your microphone.” UserHandupEventData.step tells you which step it is: .request raise hand, .cancel lower hand, .confirmOpen accept the request, .rejectOpen decline the request.

Room state events

For screen sharing, roomShareDidStart is based on the RTC media track: it’s reported as soon as the remote screen track arrives, so you can render the shared video directly when you receive it. shareBroadcastDidStart / shareBroadcastDidFinish fire only for iOS full-screen sharing, and only on the sharer’s own side. They distinguish “the listener is attached” from “there is actually video”; for how to wire them up, see Screen sharing. When the host turns on “mute all” or “camera off for everyone,” the SDK automatically turns off the local devices of non-host members and additionally reports the corresponding member media state event. The payload of roomTitleDidChange carries title and previousTitle, and both main meeting renames and sub-meeting renames (adminUpdateSubMeetingTitle) trigger it. It has no opUid: renaming a meeting has no dedicated broadcast command, and the event is derived by comparing titles after the channel properties are updated. The properties contain only the result, not the operator, and making up an operator would only mislead callers.

Message events

Both have an isPrivate flag indicating whether it’s a private message, and uid is the sender.

Host command events

For how to handle them, see Raise hand and turn-on requests.

Waiting room events


Sub-meeting events

For all three events, you need to perform the switch yourself: “exit the current meeting, then enter the target meeting.”

Sign-in and roll call events


Device events

Device events don’t depend on meeting state; the SDK starts reporting them once the instance is created, so you can use them on a pre-meeting device check page.

Audio routing events (iOS)

Both callbacks exist only on iOS (their declarations are wrapped in #if os(iOS)), and like device events, they don’t depend on meeting state. AudioRouteChangeEventData.reason is the change reason given by the system, and it’s more useful than the result itself when troubleshooting routing issues. Recovery from an interruption may be delayed because a system call hasn’t ended or the app is still in the background; the SDK fires the event only once, after audio has actually recovered. For details, see Audio routing.

Call quality events

Quality is reported through two separate feeds; pick one based on what you need, and don’t use both to drive the same UI:
  • didReceiveQualityReport fires on every report with the raw values (packet loss, RTT, jitter, bitrate, MOS), suitable for signal bar icons and detailed diagnostics panels
  • connectionQualityDidChange fires only when the level jumps to a different tier, suitable for “your network is poor” hints and proactive downgrade decisions
activeSpeakersDidChange gives a full snapshot (already sorted by volume in descending order), so just overwrite your UI with it; you don’t need to merge increments yourself. When no one is speaking, speakers is an empty array. The data structures of these four events are defined in the underlying SRTC module, so you need import SRTC to use them; for the fields, see Types. For level determination, cold-start values, and proactive layer switching, see SRTC · Call quality and active speakers.
These four events are available only when the meeting uses the SeaStart (SFU) engine—meetings that go through the CDN (Wangsu) don’t have this signaling path and receive none of them.

Receive stream status events

It’s determined per track: when a video track produces no frames for a period of time, a timeout is reported (timedOut == true), and as soon as frames resume, it’s reported again (timedOut == false). A typical use is toggling the “loading” indicator on a video tile. When the first frame arrives after you subscribe, you first receive a recovery, which you can use to turn off the initial loading indicator. The payload directly reuses the underlying SRTC ReceiveStreamStatus (requires import SRTC); for the fields, see Types. It corresponds to onReceiveStreamStatusChange:streamType:status: in the old MeetingKit.
Don’t use connectionQualityDidChange in its place. The quality tier is one value for the whole connection and tells you “whether the network is good,” not “whether this tile’s video has stopped”: when a single track stops being published, the sender’s camera freezes, or one track fails to decode, the tier can stay at excellent the whole time. Using the tier to drive a single tile’s loading indicator inevitably produces false alarms.
Unlike the four quality events above, this event is available with both engines—it’s determined by whether video frames are received locally and doesn’t depend on the SFU’s signaling path.

Out-of-meeting message events

You need to call enableIm() first; see Out-of-meeting messages. These connection events and the meeting connection events above belong to two independent paths; don’t mix them up.

Event identifier enums

The SDK also exposes two enums that list the string identifier of each event:
  • RoomEventType—in-meeting event identifiers, such as user_enter and room_share_start
  • ImEventType—out-of-meeting message event identifiers, such as call_calling
On the Swift side, events are dispatched through the SMeetingDelegate methods above. You don’t need these two enums in a normal integration; they’re useful only when you need logging instrumentation or want to align event naming with other platforms.