> ## Documentation Index
> Fetch the complete documentation index at: https://cometchat-22654f5b-docs-agent-native-development.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Events

> Handle CometChat Calls SDK v5 events on iOS for call lifecycle, participants, media state, errors, and real-time updates.

Handle call session events to build responsive UIs. The SDK provides five event listener protocols to monitor session status, participant activities, media changes, button clicks, and layout changes.

## Get CallSession Instance

The `CallSession` is a singleton that manages the active call. All event listener registrations and session control methods are accessed through this instance.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    let callSession = CallSession.shared
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    CallSession *callSession = [CallSession shared];
    ```
  </Tab>
</Tabs>

<Note>
  Remember to remove listeners when your view controller is deallocated to prevent memory leaks. Use `removeSessionStatusListener`, `removeParticipantEventListener`, etc.
</Note>

***

## Session Events

Monitor the call session lifecycle including join/leave events and connection status.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    class CallViewController: UIViewController, SessionStatusListener {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            CallSession.shared.addSessionStatusListener(self)
        }
        
        deinit {
            CallSession.shared.removeSessionStatusListener(self)
        }
        
        func onSessionJoined() {
            // Successfully connected to the session
        }

        func onSessionLeft() {
            // Left the session
            navigationController?.popViewController(animated: true)
        }

        func onSessionTimedOut() {
            // Session ended due to inactivity
            navigationController?.popViewController(animated: true)
        }

        func onConnectionLost() {
            // Network interrupted, attempting reconnection
        }

        func onConnectionRestored() {
            // Connection restored after being lost
        }

        func onConnectionClosed() {
            // Connection permanently closed
            navigationController?.popViewController(animated: true)
        }
    }
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    @interface CallViewController () <SessionStatusListener>
    @end

    @implementation CallViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
        [[CallSession shared] addSessionStatusListener:self];
    }

    - (void)dealloc {
        [[CallSession shared] removeSessionStatusListener:self];
    }

    - (void)onSessionJoined {
        // Successfully connected to the session
    }

    - (void)onSessionLeft {
        // Left the session
        [self.navigationController popViewControllerAnimated:YES];
    }

    - (void)onSessionTimedOut {
        // Session ended due to inactivity
        [self.navigationController popViewControllerAnimated:YES];
    }

    - (void)onConnectionLost {
        // Network interrupted, attempting reconnection
    }

    - (void)onConnectionRestored {
        // Connection restored after being lost
    }

    - (void)onConnectionClosed {
        // Connection permanently closed
        [self.navigationController popViewControllerAnimated:YES];
    }

    @end
    ```
  </Tab>
</Tabs>

| Event | Description |
| - | - |
| `onSessionJoined()` | Successfully connected and joined the session |
| `onSessionLeft()` | Left the session via `leaveSession()` or was removed |
| `onSessionTimedOut()` | Session ended due to inactivity timeout |
| `onConnectionLost()` | Network interrupted, SDK attempting reconnection |
| `onConnectionRestored()` | Connection restored after being lost |
| `onConnectionClosed()` | Connection permanently closed, cannot reconnect |

***

## Participant Events

Monitor participant activities including join/leave, audio/video state, hand raise, screen sharing, and recording.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    class CallViewController: UIViewController, ParticipantEventListener {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            CallSession.shared.addParticipantEventListener(self)
        }
        
        deinit {
            CallSession.shared.removeParticipantEventListener(self)
        }
        
        func onParticipantJoined(participant: Participant) {
            // A participant joined the call
        }

        func onParticipantLeft(participant: Participant) {
            // A participant left the call
        }

        func onParticipantListChanged(participants: [Participant]) {
            // Participant list updated
        }

        func onParticipantAudioMuted(participant: Participant) {}
        func onParticipantAudioUnmuted(participant: Participant) {}
        func onParticipantVideoPaused(participant: Participant) {}
        func onParticipantVideoResumed(participant: Participant) {}
        func onParticipantHandRaised(participant: Participant) {}
        func onParticipantHandLowered(participant: Participant) {}
        func onParticipantStartedScreenShare(participant: Participant) {}
        func onParticipantStoppedScreenShare(participant: Participant) {}
        func onParticipantStartedRecording(participant: Participant) {}
        func onParticipantStoppedRecording(participant: Participant) {}
        func onDominantSpeakerChanged(participant: Participant) {}
    }
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    @interface CallViewController () <ParticipantEventListener>
    @end

    @implementation CallViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
        [[CallSession shared] addParticipantEventListener:self];
    }

    - (void)dealloc {
        [[CallSession shared] removeParticipantEventListener:self];
    }

    - (void)onParticipantJoinedWithParticipant:(Participant *)participant {
        // A participant joined the call
    }

    - (void)onParticipantLeftWithParticipant:(Participant *)participant {
        // A participant left the call
    }

    - (void)onParticipantListChangedWithParticipants:(NSArray<Participant *> *)participants {
        // Participant list updated
    }

    // Other callbacks...

    @end
    ```
  </Tab>
</Tabs>

| Event | Parameter | Description |
| - | - | - |
| `onParticipantJoined` | `Participant` | A participant connected to the call |
| `onParticipantLeft` | `Participant` | A participant disconnected from the call |
| `onParticipantListChanged` | `[Participant]` | Participant list updated |
| `onParticipantAudioMuted` | `Participant` | A participant muted their microphone |
| `onParticipantAudioUnmuted` | `Participant` | A participant unmuted their microphone |
| `onParticipantVideoPaused` | `Participant` | A participant turned off their camera |
| `onParticipantVideoResumed` | `Participant` | A participant turned on their camera |
| `onParticipantHandRaised` | `Participant` | A participant raised their hand |
| `onParticipantHandLowered` | `Participant` | A participant lowered their hand |
| `onParticipantStartedScreenShare` | `Participant` | A participant started screen sharing |
| `onParticipantStoppedScreenShare` | `Participant` | A participant stopped screen sharing |
| `onParticipantStartedRecording` | `Participant` | A participant started recording |
| `onParticipantStoppedRecording` | `Participant` | A participant stopped recording |
| `onDominantSpeakerChanged` | `Participant` | The active speaker changed |

***

## Media Events

Monitor your local media state changes including audio/video status, recording, and device changes.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    class CallViewController: UIViewController, MediaEventsListener {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            CallSession.shared.addMediaEventsListener(self)
        }
        
        deinit {
            CallSession.shared.removeMediaEventsListener(self)
        }
        
        func onAudioMuted() {
            // Your microphone was muted
        }

        func onAudioUnMuted() {
            // Your microphone was unmuted
        }

        func onVideoPaused() {
            // Your camera was turned off
        }

        func onVideoResumed() {
            // Your camera was turned on
        }

        func onRecordingStarted() {
            // Call recording started
        }

        func onRecordingStopped() {
            // Call recording stopped
        }

        func onAudioModeChanged(audioMode: AudioMode) {
            // Audio output device changed
        }

        func onCameraFacingChanged(cameraFacing: CameraFacing) {
            // Camera switched between front and back
        }
    }
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    @interface CallViewController () <MediaEventsListener>
    @end

    @implementation CallViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
        [[CallSession shared] addMediaEventsListener:self];
    }

    - (void)dealloc {
        [[CallSession shared] removeMediaEventsListener:self];
    }

    - (void)onAudioMuted {
        // Your microphone was muted
    }

    - (void)onAudioUnMuted {
        // Your microphone was unmuted
    }

    - (void)onVideoPaused {
        // Your camera was turned off
    }

    - (void)onVideoResumed {
        // Your camera was turned on
    }

    - (void)onRecordingStarted {
        // Call recording started
    }

    - (void)onRecordingStopped {
        // Call recording stopped
    }

    - (void)onAudioModeChangedWithAudioMode:(AudioMode)audioMode {
        // Audio output device changed
    }

    - (void)onCameraFacingChangedWithCameraFacing:(CameraFacing)cameraFacing {
        // Camera switched between front and back
    }

    // Other callbacks...

    @end
    ```
  </Tab>
</Tabs>

| Event | Parameter | Description |
| - | - | - |
| `onAudioMuted` | - | Your microphone was muted |
| `onAudioUnMuted` | - | Your microphone was unmuted |
| `onVideoPaused` | - | Your camera was turned off |
| `onVideoResumed` | - | Your camera was turned on |
| `onRecordingStarted` | - | Call recording started |
| `onRecordingStopped` | - | Call recording stopped |
| `onAudioModeChanged` | `AudioMode` | Audio output device changed |
| `onCameraFacingChanged` | `CameraFacing` | Camera switched between front and back |

<Note>
  `MediaEventsListener` has **no** screen-share callback. Screen sharing is observed on
  [`ParticipantEventListener`](#participanteventlistener) via `onParticipantStartedScreenShare` /
  `onParticipantStoppedScreenShare` — and on iOS those are **receive-only**: the SDK reports a share
  started from another client, but cannot start one locally (that needs a Broadcast Upload Extension).
</Note>

<AccordionGroup>
  <Accordion title="AudioMode Values">
    | Value | Description |
    | - | - |
    | `.speaker` | Audio routed through device loudspeaker |
    | `.earpiece` | Audio routed through phone earpiece |
    | `.bluetooth` | Audio routed through connected Bluetooth device |
    | `.headphones` | Audio routed through wired headphones |
  </Accordion>

  <Accordion title="CameraFacing Values">
    | Value | Description |
    | - | - |
    | `.FRONT` | Front-facing (selfie) camera is active |
    | `.BACK` | Rear-facing (main) camera is active |
  </Accordion>
</AccordionGroup>

***

## Button Click Events

Intercept UI button clicks from the default call interface to add custom behavior or analytics.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    class CallViewController: UIViewController, ButtonClickListener {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            CallSession.shared.addButtonClickListener(self)
        }
        
        deinit {
            CallSession.shared.removeButtonClickListener(self)
        }
        
        func onLeaveSessionButtonClicked() {
            // Leave button tapped
        }

        func onToggleAudioButtonClicked() {
            // Mute/unmute button tapped
        }

        func onToggleVideoButtonClicked() {
            // Video on/off button tapped
        }

        func onSwitchCameraButtonClicked() {}
        func onRaiseHandButtonClicked() {}
        func onShareInviteButtonClicked() {}
        func onChangeLayoutButtonClicked() {}
        func onParticipantListButtonClicked() {}
        func onChatButtonClicked() {}
        func onRecordingToggleButtonClicked() {}
    }
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    @interface CallViewController () <ButtonClickListener>
    @end

    @implementation CallViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
        [[CallSession shared] addButtonClickListener:self];
    }

    - (void)dealloc {
        [[CallSession shared] removeButtonClickListener:self];
    }

    - (void)onLeaveSessionButtonClicked {
        // Leave button tapped
    }

    - (void)onToggleAudioButtonClicked {
        // Mute/unmute button tapped
    }

    - (void)onToggleVideoButtonClicked {
        // Video on/off button tapped
    }

    // Other callbacks...

    @end
    ```
  </Tab>
</Tabs>

| Event | Description |
| - | - |
| `onLeaveSessionButtonClicked` | Leave/end call button was tapped |
| `onToggleAudioButtonClicked` | Mute/unmute button was tapped |
| `onToggleVideoButtonClicked` | Video on/off button was tapped |
| `onSwitchCameraButtonClicked` | Camera switch button was tapped |
| `onRaiseHandButtonClicked` | Raise hand button was tapped |
| `onShareInviteButtonClicked` | Share/invite button was tapped |
| `onChangeLayoutButtonClicked` | Layout change button was tapped |
| `onParticipantListButtonClicked` | Participant list button was tapped |
| `onChatButtonClicked` | In-call chat button was tapped |
| `onRecordingToggleButtonClicked` | Recording toggle button was tapped |

<Note>
  Button click events fire before the SDK's default action executes. Use these to add custom logic alongside default behavior.
</Note>

***

## Layout Events

Monitor layout changes including layout type switches and Picture-in-Picture mode transitions.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    class CallViewController: UIViewController, LayoutListener {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            CallSession.shared.addLayoutListener(self)
        }
        
        deinit {
            CallSession.shared.removeLayoutListener(self)
        }
        
        func onCallLayoutChanged(layoutType: LayoutType) {
            // Layout changed (TILE, SPOTLIGHT)
        }

        func onParticipantListVisible() {
            // Participant list panel opened
        }

        func onParticipantListHidden() {
            // Participant list panel closed
        }

        func onPictureInPictureLayoutEnabled() {
            // Entered PiP mode
        }

        func onPictureInPictureLayoutDisabled() {
            // Exited PiP mode
        }
    }
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    @interface CallViewController () <LayoutListener>
    @end

    @implementation CallViewController

    - (void)viewDidLoad {
        [super viewDidLoad];
        [[CallSession shared] addLayoutListener:self];
    }

    - (void)dealloc {
        [[CallSession shared] removeLayoutListener:self];
    }

    - (void)onCallLayoutChangedWithLayoutType:(LayoutType)layoutType {
        // Layout changed (TILE, SPOTLIGHT)
    }

    - (void)onParticipantListVisible {
        // Participant list panel opened
    }

    - (void)onParticipantListHidden {
        // Participant list panel closed
    }

    - (void)onPictureInPictureLayoutEnabled {
        // Entered PiP mode
    }

    - (void)onPictureInPictureLayoutDisabled {
        // Exited PiP mode
    }

    @end
    ```
  </Tab>
</Tabs>

| Event | Parameter | Description |
| - | - | - |
| `onCallLayoutChanged` | `LayoutType` | Call layout changed |
| `onParticipantListVisible` | - | Participant list panel was opened |
| `onParticipantListHidden` | - | Participant list panel was closed |
| `onPictureInPictureLayoutEnabled` | - | Call entered Picture-in-Picture mode |
| `onPictureInPictureLayoutDisabled` | - | Call exited Picture-in-Picture mode |

<Accordion title="LayoutType Values">
  | Value | Description | Best For |
  | - | - | - |
  | `.tile` | Grid layout with equally-sized tiles | Group discussions, team meetings |
  | `.spotlight` | Large view for active speaker, small tiles for others | Presentations, one-on-one calls |
</Accordion>

***

## Clear All Listeners

Remove all registered listeners at once. Useful when cleaning up resources.

<Tabs>
  <Tab title="Swift">
    ```swift theme={null}
    CallSession.shared.clearAllListeners()
    ```
  </Tab>

  <Tab title="Objective-C">
    ```objectivec theme={null}
    [[CallSession shared] clearAllListeners];
    ```
  </Tab>
</Tabs>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.