Pin/Unpin Participants - iOS
In a live stream setup, you often want to control which participant is actively visible on screen — whether it’s the host, a special guest, or someone screen sharing. To manage this dynamically, the Participant class provides two key methods:
-
pin()– Focus on a specific participant’s camera or screen share -
unpin()– Remove that focus and return to the default layout
This allows you to programmatically decide who gets the spotlight in your live stream layout.
pin()
The pin() method makes it easy to bring a host camera or screen share front and center in the broadcast layout. Once pinned, you can write the layout logic to place this host in the primary frame, e.g. fullscreen or in a highlighted position.
pin() and unpin() take a PinType (.SHARE_AND_CAM by default, .CAM or .SHARE). Both are async throws, so call them with try await inside a Task. They throw ERROR_ACTION_PERFORMED_BEFORE_ROOM_JOINED when you are not in the room and ERROR_ROOM_RECONNECTING while the room is reconnecting. These two errors are also sent to onError(error:).
func pinParticipant(participant: Participant, pinType: PinType) {
Task {
do {
try await participant.pin(pinType)
} catch {
print("Failed to pin participant: \(error)")
}
}
}
unpin()
When a host is no longer the focus (e.g. their segment is over), you can reset their pinned state using unpin(). This allows your live stream UI to revert to a default grid view or automatically promote the next speaker.
func unpinParticipant(participant: Participant, pinType: PinType) {
Task {
do {
try await participant.unpin(pinType)
} catch {
print("Failed to unpin participant: \(error)")
}
}
}
Events associated with pin/unpin
The following callbacks are received when a host is pinned or unpinned in the livestream.
- All participants-including all the hosts and audience members will receive a callback on the
onPinStateChangedevent ofRoomEventListener, with theparticipantIdof the participant, its new pinstate(aParticipantPinStatewithcamandshare), andpinnedBy, the ID of the participant who changed the pin (nilif the server did not say). - The event fires for both pin and unpin. To know what is pinned across the room, read
room.pinnedParticipants. A participant is in it only while their camera or screen share is pinned.
extension LiveStreamViewController: RoomEventListener {
func onPinStateChanged(participantId: String, state: ParticipantPinState, pinnedBy: String?) {
// Update your UI to reflect the new pin state
print("Participant \(participantId) pin state changed by \(pinnedBy ?? "unknown"), cam pinned: \(state.cam), share pinned: \(state.share)")
}
}
- Based on the
onPinStateChangedevent, you should update your live stream layout for all participants (including the audience) to reflect the current pinned participant. This means conditionally rendering the pinned participant in the main view or spotlight area across all clients.
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

