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

# Events

> Listen and respond to user actions and state changes in CometChat UI Kit

<Accordion title="AI Integration Quick Reference">
  ```json theme={null}
  {
    "category": "events",
    "subscriptionPattern": {
      "addListener": "CometChat{Category}Events.addListener(listenerId, self)",
      "removeListener": "CometChat{Category}Events.removeListener(listenerId)"
    },
    "eventCategories": [
      {
        "name": "userEvents",
        "listenerClass": "CometChatUserEvents",
        "protocol": "CometChatUserEventListener",
        "events": [
          {"name": "ccUserBlocked", "payload": "User", "description": "User was blocked"},
          {"name": "ccUserUnblocked", "payload": "User", "description": "User was unblocked"}
        ]
      },
      {
        "name": "groupEvents",
        "listenerClass": "CometChatGroupEvents",
        "protocol": "CometChatGroupEventListener",
        "events": [
          {"name": "ccGroupCreated", "payload": "Group", "description": "New group created"},
          {"name": "ccGroupDeleted", "payload": "Group", "description": "Group deleted"},
          {"name": "ccGroupMemberJoined", "payload": "(User, Group)", "description": "User joined group"},
          {"name": "ccGroupLeft", "payload": "(ActionMessage, User, Group)", "description": "User left group"},
          {"name": "ccGroupMemberKicked", "payload": "(ActionMessage, User, User, Group)", "description": "Member kicked"},
          {"name": "ccGroupMemberBanned", "payload": "(ActionMessage, User, User, Group)", "description": "Member banned"},
          {"name": "ccOwnershipChanged", "payload": "(Group, GroupMember)", "description": "Ownership transferred"}
        ]
      },
      {
        "name": "conversationEvents",
        "listenerClass": "CometChatConversationEvents",
        "protocol": "CometChatConversationEventListener",
        "events": [
          {"name": "ccConversationDeleted", "payload": "Conversation", "description": "Conversation deleted"},
          {"name": "ccUpdateConversation", "payload": "Conversation", "description": "Conversation updated"}
        ]
      },
      {
        "name": "messageEvents",
        "listenerClass": "CometChatMessageEvents",
        "protocol": "CometChatMessageEventListener",
        "events": [
          {"name": "onMessageSent", "payload": "(BaseMessage, MessageStatus)", "description": "Message sent"},
          {"name": "onMessageEdit", "payload": "(BaseMessage, MessageStatus)", "description": "Message edited"},
          {"name": "onMessageDelete", "payload": "(BaseMessage, MessageStatus)", "description": "Message deleted"},
          {"name": "onMessageRead", "payload": "BaseMessage", "description": "Message read"},
          {"name": "onMessageReact", "payload": "(BaseMessage, Reaction)", "description": "Reaction added"}
        ]
      },
      {
        "name": "callEvents",
        "listenerClass": "CometChatCallEvents",
        "protocol": "CometChatCallEventListener",
        "events": [
          {"name": "onCallInitiated", "payload": "Call", "description": "Outgoing call started"},
          {"name": "onCallEnded", "payload": "Call", "description": "Call ended"},
          {"name": "onIncomingCallAccepted", "payload": "Call", "description": "Incoming call accepted"},
          {"name": "onOutgoingCallAccepted", "payload": "Call", "description": "Outgoing call accepted"}
        ]
      }
    ]
  }
  ```
</Accordion>

Events allow different parts of your app to communicate without direct dependencies. When a user performs an action (like blocking someone, deleting a conversation, or sending a message), events are emitted so other components can react accordingly.

## How Events Work

1. **Subscribe** to events using `addListener` in `viewDidLoad`
2. **React** to events in your listener callback methods
3. **Unsubscribe** using `removeListener` in `viewWillDisappear`

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class MyViewController: UIViewController {
    
    private let listenerId = "my-unique-listener"
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Subscribe to events
        CometChatUserEvents.addListener(listenerId, self)
        CometChatGroupEvents.addListener(listenerId, self)
        CometChatConversationEvents.addListener(listenerId, self)
        CometChatMessageEvents.addListener(listenerId, self)
        CometChatCallEvents.addListener(listenerId, self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        
        // Unsubscribe to prevent memory leaks
        CometChatUserEvents.removeListener(listenerId)
        CometChatGroupEvents.removeListener(listenerId)
        CometChatConversationEvents.removeListener(listenerId)
        CometChatMessageEvents.removeListener(listenerId)
        CometChatCallEvents.removeListener(listenerId)
    }
}
```

## User Events

Listen for user-related actions like blocking and unblocking.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class UserEventsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        CometChatUserEvents.addListener("user-listener", self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        CometChatUserEvents.removeListener("user-listener")
    }
}

extension UserEventsViewController: CometChatUserEventListener {
    
    func ccUserBlocked(user: User) {
        print("Blocked: \(user.name ?? "")")
        // Update UI - hide user from lists, disable messaging
    }
    
    func ccUserUnblocked(user: User) {
        print("Unblocked: \(user.name ?? "")")
        // Update UI - show user in lists, enable messaging
    }
}
```

### Emit User Events

Notify other components when you block/unblock a user:

```swift lines theme={null}
// After blocking a user
CometChatUserEvents.ccUserBlocked(user: blockedUser)

// After unblocking a user
CometChatUserEvents.ccUserUnblocked(user: unblockedUser)
```

### User Events Reference

| Event             | Description                          |
| ----------------- | ------------------------------------ |
| `ccUserBlocked`   | User was blocked by logged-in user   |
| `ccUserUnblocked` | User was unblocked by logged-in user |

## Group Events

Listen for group-related actions like creating groups, adding members, and role changes.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class GroupEventsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        CometChatGroupEvents.addListener("group-listener", self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        CometChatGroupEvents.removeListener("group-listener")
    }
}

extension GroupEventsViewController: CometChatGroupEventListener {
    
    // Group lifecycle
    func onGroupCreate(group: Group) {
        print("Group created: \(group.name ?? "")")
    }
    
    func onGroupDelete(group: Group) {
        print("Group deleted: \(group.name ?? "")")
    }
    
    func onCreateGroupClick() {
        print("Create group button tapped")
    }
    
    // Member join/leave
    func onGroupMemberJoin(joinedUser: User, joinedGroup: Group) {
        print("\(joinedUser.name ?? "") joined \(joinedGroup.name ?? "")")
    }
    
    func onGroupMemberLeave(leftUser: User, leftGroup: Group) {
        print("\(leftUser.name ?? "") left \(leftGroup.name ?? "")")
    }
    
    func onGroupMemberAdd(group: Group, members: [GroupMember], addedBy: User) {
        print("\(members.count) members added to \(group.name ?? "")")
    }
    
    // Moderation
    func onGroupMemberKick(kickedUser: User, kickedGroup: Group) {
        print("\(kickedUser.name ?? "") kicked from \(kickedGroup.name ?? "")")
    }
    
    func onGroupMemberBan(bannedUser: User, bannedGroup: Group) {
        print("\(bannedUser.name ?? "") banned from \(bannedGroup.name ?? "")")
    }
    
    func onGroupMemberUnban(unbannedUserUser: User, unbannedUserGroup: Group) {
        print("\(unbannedUserUser.name ?? "") unbanned")
    }
    
    // Role changes
    func onGroupMemberChangeScope(updatedBy: User, updatedUser: User, scopeChangedTo: CometChat.MemberScope, scopeChangedFrom: CometChat.MemberScope, group: Group) {
        print("\(updatedUser.name ?? "") role: \(scopeChangedFrom) → \(scopeChangedTo)")
    }
    
    func onOwnershipChange(group: Group?, member: GroupMember?) {
        print("Ownership transferred to \(member?.name ?? "")")
    }
}
```

### Emit Group Events

Notify other components about group actions:

```swift lines theme={null}
// Group created
CometChatGroupEvents.emitOnGroupCreate(group: newGroup)

// Group deleted
CometChatGroupEvents.emitOnGroupDelete(group: deletedGroup)

// Member joined
CometChatGroupEvents.emitOnGroupMemberJoin(joinedUser: user, joinedGroup: group)

// Member left
CometChatGroupEvents.emitOnGroupMemberLeave(leftUser: user, leftGroup: group)

// Members added
CometChatGroupEvents.emitOnGroupMemberAdd(group: group, members: newMembers, addedBy: currentUser)

// Member kicked
CometChatGroupEvents.emitOnGroupMemberKick(kickedUser: user, kickedGroup: group, kickedBy: admin)

// Member banned
CometChatGroupEvents.emitOnGroupMemberBan(bannedUser: user, bannedGroup: group, bannedBy: admin)

// Member unbanned
CometChatGroupEvents.emitOnGroupMemberUnban(unbannedUserUser: user, unbannedUserGroup: group, unbannedBy: admin)

// Role changed
CometChatGroupEvents.emitOnGroupMemberChangeScope(
    updatedBy: admin,
    updatedUser: member,
    scopeChangedTo: .admin,
    scopeChangedFrom: .participant,
    group: group
)
```

### Group Events Reference

| Event                      | Description                 |
| -------------------------- | --------------------------- |
| `onGroupCreate`            | New group created           |
| `onGroupDelete`            | Group deleted               |
| `onCreateGroupClick`       | Create group button tapped  |
| `onGroupMemberJoin`        | User joined a group         |
| `onGroupMemberLeave`       | User left a group           |
| `onGroupMemberAdd`         | Members added to group      |
| `onGroupMemberKick`        | Member kicked from group    |
| `onGroupMemberBan`         | Member banned from group    |
| `onGroupMemberUnban`       | Member unbanned             |
| `onGroupMemberChangeScope` | Member role changed         |
| `onOwnershipChange`        | Group ownership transferred |

## Conversation Events

Listen for conversation-level actions like delete and update.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ConversationEventsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        CometChatConversationEvents.addListener("conversation-listener", self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        CometChatConversationEvents.removeListener("conversation-listener")
    }
}

extension ConversationEventsViewController: CometChatConversationEventListener {
    
    func ccConversationDeleted(conversation: Conversation) {
        print("Conversation deleted: \(conversation.conversationId ?? "")")
        // Remove from local list, update UI
    }
    
    func ccUpdateConversation(conversation: Conversation) {
        print("Conversation updated: \(conversation.conversationId ?? "")")
        // Refresh conversation data in UI
    }
}
```

### Emit Conversation Events

```swift lines theme={null}
// Conversation deleted
CometChatConversationEvents.ccConversationDelete(conversation: deletedConversation)

// Conversation updated
CometChatConversationEvents.ccUpdateConversation(conversation: updatedConversation)
```

### Conversation Events Reference

| Event                   | Description              |
| ----------------------- | ------------------------ |
| `ccConversationDeleted` | Conversation was deleted |
| `ccUpdateConversation`  | Conversation was updated |

## Message Events

Listen for message-related actions like send, edit, delete, and reactions.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class MessageEventsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        CometChatMessageEvents.addListener("message-listener", self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        CometChatMessageEvents.removeListener("message-listener")
    }
}

extension MessageEventsViewController: CometChatMessageEventListener {
    
    // Message lifecycle
    func onMessageSent(message: BaseMessage, status: MessageStatus) {
        switch status {
        case .inProgress:
            print("Sending...")
        case .success:
            print("Message sent: \(message.id)")
        case .error:
            print("Send failed")
        @unknown default:
            break
        }
    }
    
    func onMessageEdit(message: BaseMessage, status: MessageStatus) {
        print("Message edited: \(message.id)")
    }
    
    func onMessageDelete(message: BaseMessage, status: MessageStatus) {
        print("Message deleted: \(message.id)")
    }
    
    func onMessageRead(message: BaseMessage) {
        print("Message read: \(message.id)")
    }
    
    func onMessageReply(message: BaseMessage, status: MessageStatus) {
        print("Reply sent to: \(message.id)")
    }
    
    // Reactions
    func onMessageReact(message: BaseMessage, reaction: CometChatMessageReaction) {
        print("Reaction: \(reaction.reaction ?? "")")
    }
    
    func onLiveReaction(reaction: TransientMessage) {
        print("Live reaction received")
    }
    
    // Thread updates
    func onParentMessageUpdate(message: BaseMessage) {
        print("Thread parent updated: \(message.id)")
    }
    
    // Navigation
    func onViewInformation(user: User) {
        print("View user info: \(user.name ?? "")")
    }
    
    func onViewInformation(group: Group) {
        print("View group info: \(group.name ?? "")")
    }
    
    // Calls from message screen
    func onVoiceCall(user: User) {
        print("Voice call to: \(user.name ?? "")")
    }
    
    func onVideoCall(user: User) {
        print("Video call to: \(user.name ?? "")")
    }
    
    func onVoiceCall(group: Group) {
        print("Group voice call: \(group.name ?? "")")
    }
    
    func onVideoCall(group: Group) {
        print("Group video call: \(group.name ?? "")")
    }
    
    // Errors
    func onMessageError(error: CometChatException) {
        print("Error: \(error.errorDescription)")
    }
}
```

### Emit Message Events

```swift lines theme={null}
// Message sent (with status)
CometChatMessageEvents.emitOnMessageSent(message: sentMessage, status: .success)

// Message edited
CometChatMessageEvents.emitOnMessageEdit(message: editedMessage, status: .success)

// Message deleted
CometChatMessageEvents.emitOnMessageDelete(message: deletedMessage)

// Message read
CometChatMessageEvents.emitOnMessageRead(message: readMessage)

// Live reaction
CometChatMessageEvents.emitOnLiveReaction(reaction: transientMessage)

// View user/group info
CometChatMessageEvents.emitOnViewInformation(user: selectedUser)

// Thread parent updated
CometChatMessageEvents.emitOnParentMessageUpdate(message: parentMessage)
```

### Message Events Reference

| Event                   | Description                                  |
| ----------------------- | -------------------------------------------- |
| `onMessageSent`         | Message sent (inProgress, success, or error) |
| `onMessageEdit`         | Message edited                               |
| `onMessageDelete`       | Message deleted                              |
| `onMessageRead`         | Message marked as read                       |
| `onMessageReply`        | Reply sent to a message                      |
| `onMessageReact`        | Reaction added to message                    |
| `onLiveReaction`        | Live reaction sent                           |
| `onParentMessageUpdate` | Thread parent message updated                |
| `onViewInformation`     | Info button tapped (user or group)           |
| `onVoiceCall`           | Voice call initiated                         |
| `onVideoCall`           | Video call initiated                         |
| `onMessageError`        | Message operation failed                     |

## Call Events

Listen for call-related actions like initiating, accepting, and ending calls.

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class CallEventsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        CometChatCallEvents.addListener("call-listener", self)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        CometChatCallEvents.removeListener("call-listener")
    }
}

extension CallEventsViewController: CometChatCallEventListener {
    
    // Outgoing calls
    func onCallInitiated(call: Call) {
        print("Calling: \(call.receiverUid)")
    }
    
    func onOutgoingCallAccepted(call: Call) {
        print("Call accepted by recipient")
    }
    
    func onOutgoingCallRejected(call: Call) {
        print("Call rejected by recipient")
    }
    
    // Incoming calls
    func onIncomingCallAccepted(call: Call) {
        print("You accepted the call")
    }
    
    func onIncomingCallRejected(call: Call) {
        print("You rejected the call")
    }
    
    // Call ended
    func onCallEnded(call: Call) {
        print("Call ended")
    }
}
```

### Emit Call Events

```swift lines theme={null}
// Call initiated
CometChatCallEvents.emitOnCallInitiated(call: outgoingCall)

// Call ended
CometChatCallEvents.emitOnCallEnded(call: endedCall)

// Incoming call accepted
CometChatCallEvents.emitOnIncomingCallAccepted(call: acceptedCall)

// Incoming call rejected
CometChatCallEvents.emitOnIncomingCallRejected(call: rejectedCall)

// Outgoing call accepted
CometChatCallEvents.emitOnOutgoingCallAccepted(call: acceptedCall)

// Outgoing call rejected
CometChatCallEvents.emitOnOutgoingCallRejected(call: rejectedCall)
```

### Call Events Reference

| Event                    | Description                   |
| ------------------------ | ----------------------------- |
| `onCallInitiated`        | Outgoing call started         |
| `onOutgoingCallAccepted` | Recipient accepted the call   |
| `onOutgoingCallRejected` | Recipient rejected the call   |
| `onIncomingCallAccepted` | You accepted an incoming call |
| `onIncomingCallRejected` | You rejected an incoming call |
| `onCallEnded`            | Call ended (any reason)       |

## Complete Example: App-Wide Event Manager

Create a centralized event manager to handle events across your entire app:

```swift lines theme={null}
import UIKit
import CometChatUIKitSwift
import CometChatSDK

// MARK: - Singleton Event Manager
class ChatEventManager {
    
    static let shared = ChatEventManager()
    private let listenerId = "app-event-manager"
    
    private init() {}
    
    func startListening() {
        CometChatUserEvents.addListener(listenerId, self)
        CometChatGroupEvents.addListener(listenerId, self)
        CometChatConversationEvents.addListener(listenerId, self)
        CometChatMessageEvents.addListener(listenerId, self)
        CometChatCallEvents.addListener(listenerId, self)
    }
    
    func stopListening() {
        CometChatUserEvents.removeListener(listenerId)
        CometChatGroupEvents.removeListener(listenerId)
        CometChatConversationEvents.removeListener(listenerId)
        CometChatMessageEvents.removeListener(listenerId)
        CometChatCallEvents.removeListener(listenerId)
    }
}

// MARK: - User Events
extension ChatEventManager: CometChatUserEventListener {
    func onUserBlock(user: User) {
        NotificationCenter.default.post(name: .userBlocked, object: user)
    }
    
    func onUserUnblock(user: User) {
        NotificationCenter.default.post(name: .userUnblocked, object: user)
    }
}

// MARK: - Group Events
extension ChatEventManager: CometChatGroupEventListener {
    func onGroupCreate(group: Group) {
        NotificationCenter.default.post(name: .groupCreated, object: group)
    }
    
    func onGroupDelete(group: Group) {
        NotificationCenter.default.post(name: .groupDeleted, object: group)
    }
    
    func onGroupMemberJoin(joinedUser: User, joinedGroup: Group) {
        NotificationCenter.default.post(name: .memberJoined, object: nil, 
            userInfo: ["user": joinedUser, "group": joinedGroup])
    }
    
    func onGroupMemberLeave(leftUser: User, leftGroup: Group) {
        NotificationCenter.default.post(name: .memberLeft, object: nil,
            userInfo: ["user": leftUser, "group": leftGroup])
    }
    
    // Implement other required methods...
    func onGroupMemberAdd(group: Group, members: [GroupMember], addedBy: User) {}
    func onGroupMemberKick(kickedUser: User, kickedGroup: Group) {}
    func onGroupMemberBan(bannedUser: User, bannedGroup: Group) {}
    func onGroupMemberUnban(unbannedUserUser: User, unbannedUserGroup: Group) {}
    func onGroupMemberChangeScope(updatedBy: User, updatedUser: User, scopeChangedTo: CometChat.MemberScope, scopeChangedFrom: CometChat.MemberScope, group: Group) {}
    func onOwnershipChange(group: Group?, member: GroupMember?) {}
    func onCreateGroupClick() {}
}

// MARK: - Conversation Events
extension ChatEventManager: CometChatConversationEventListener {
    func ccConversationDeleted(conversation: Conversation) {
        NotificationCenter.default.post(name: .conversationDeleted, object: conversation)
    }
    
    func ccUpdateConversation(conversation: Conversation) {
        NotificationCenter.default.post(name: .conversationUpdated, object: conversation)
    }
}

// MARK: - Message Events
extension ChatEventManager: CometChatMessageEventListener {
    func onMessageSent(message: BaseMessage, status: MessageStatus) {
        if status == .success {
            NotificationCenter.default.post(name: .messageSent, object: message)
        }
    }
    
    // Implement other required methods...
    func onMessageEdit(message: BaseMessage, status: MessageStatus) {}
    func onMessageDelete(message: BaseMessage, status: MessageStatus) {}
    func onMessageRead(message: BaseMessage) {}
    func onLiveReaction(reaction: TransientMessage) {}
    func onMessageReact(message: BaseMessage, reaction: CometChatMessageReaction) {}
    func onParentMessageUpdate(message: BaseMessage) {}
    func onViewInformation(user: User) {}
    func onViewInformation(group: Group) {}
    func onVoiceCall(user: User) {}
    func onVideoCall(user: User) {}
    func onVoiceCall(group: Group) {}
    func onVideoCall(group: Group) {}
    func onMessageError(error: CometChatException) {}
    func onMessageReply(message: BaseMessage, status: MessageStatus) {}
}

// MARK: - Call Events
extension ChatEventManager: CometChatCallEventListener {
    func onCallInitiated(call: Call) {
        NotificationCenter.default.post(name: .callStarted, object: call)
    }
    
    func onCallEnded(call: Call) {
        NotificationCenter.default.post(name: .callEnded, object: call)
    }
    
    func onIncomingCallAccepted(call: Call) {}
    func onIncomingCallRejected(call: Call) {}
    func onOutgoingCallAccepted(call: Call) {}
    func onOutgoingCallRejected(call: Call) {}
}

// MARK: - Notification Names
extension Notification.Name {
    static let userBlocked = Notification.Name("userBlocked")
    static let userUnblocked = Notification.Name("userUnblocked")
    static let groupCreated = Notification.Name("groupCreated")
    static let groupDeleted = Notification.Name("groupDeleted")
    static let memberJoined = Notification.Name("memberJoined")
    static let memberLeft = Notification.Name("memberLeft")
    static let conversationDeleted = Notification.Name("conversationDeleted")
    static let conversationUpdated = Notification.Name("conversationUpdated")
    static let messageSent = Notification.Name("messageSent")
    static let callStarted = Notification.Name("callStarted")
    static let callEnded = Notification.Name("callEnded")
}
```

### Using the Event Manager

```swift lines theme={null}
// AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Start listening for events app-wide
        ChatEventManager.shared.startListening()
        
        return true
    }
}

// Any ViewController
class MyViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Listen for specific events via NotificationCenter
        NotificationCenter.default.addObserver(
            self,
            selector: #selector(handleUserBlocked),
            name: .userBlocked,
            object: nil
        )
    }
    
    @objc private func handleUserBlocked(_ notification: Notification) {
        guard let user = notification.object as? User else { return }
        print("User blocked: \(user.name ?? "")")
        // Update your UI
    }
    
    deinit {
        NotificationCenter.default.removeObserver(self)
    }
}
```

## Best Practices

1. **Always remove listeners** - Call `removeListener` in `viewWillDisappear` to prevent memory leaks

2. **Use unique listener IDs** - Avoid conflicts between components by using descriptive, unique IDs

3. **Update UI on main thread** - Dispatch UI updates to the main thread when handling events

4. **Don't emit unnecessarily** - Only emit events when state actually changes

5. **Use a central manager** - For app-wide event handling, create a singleton manager

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Methods" href="/ui-kit/ios/methods">
    Reference for UI Kit wrapper methods.
  </Card>

  <Card title="Message List" href="/ui-kit/ios/message-list">
    Display and customize chat messages.
  </Card>

  <Card title="Conversations" href="/ui-kit/ios/conversations">
    Manage conversation lists.
  </Card>

  <Card title="Groups" href="/ui-kit/ios/groups">
    Work with group chat functionality.
  </Card>
</CardGroup>

***
