Skip to main content
CometChat UI Kit provides production-ready components that work together to deliver a complete chat experience. This guide shows how to implement each core feature with copy-paste code examples.

Instant Messaging

Send and receive text messages in real-time.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ChatViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // For one-on-one chat
        let messagesVC = CometChatMessages()
        
        // Set the user to chat with
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}
Components Used:

Media Sharing

Share images, videos, audio files, and documents.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class MediaChatViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let messagesVC = CometChatMessages()
        
        // The message composer automatically includes media sharing options
        // Users can tap the attachment button to share:
        // - Photos from library
        // - Camera capture
        // - Documents
        // - Audio files
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // Send media programmatically
    func sendImage(to receiverUID: String, imageURL: URL) {
        let mediaMessage = MediaMessage(
            receiverUid: receiverUID,
            fileurl: imageURL.absoluteString,
            messageType: .image,
            receiverType: .user
        )
        
        CometChat.sendMediaMessage(message: mediaMessage) { message in
            print("Image sent successfully")
        } onError: { error in
            print("Error sending image: \(error?.errorDescription ?? "")")
        }
    }
}
Supported Media Types:
TypeBubble Component
ImagesImage Bubble
VideosVideo Bubble
AudioAudio Bubble
FilesFile Bubble

Read Receipts

Show when messages are delivered and read.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ReceiptsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Read receipts are enabled by default
        let messagesVC = CometChatMessages()
        
        // To hide receipts:
        // messagesVC.hideReceipts = true
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // View detailed message information
    func showMessageInfo(for message: BaseMessage) {
        let messageInfo = CometChatMessageInformation()
        messageInfo.set(message: message)
        navigationController?.pushViewController(messageInfo, animated: true)
    }
}
Receipt States:
  • ✓ Sent - Message sent to server
  • ✓✓ Delivered - Message delivered to recipient’s device
  • ✓✓ (blue) Read - Recipient has seen the message
Components Used:

Mark As Unread

Let users mark messages as unread to revisit later.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class UnreadMessagesViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let messagesVC = CometChatMessages()
        
        // Enable starting from first unread message
        messagesVC.scrollToUnreadMessages = true
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // Mark a message as unread programmatically
    func markAsUnread(message: BaseMessage) {
        CometChat.markAsUnread(
            baseMessage: message
        ) { _ in
            print("Marked as unread")
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}

Typing Indicators

Show when users are typing in real-time.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class TypingIndicatorViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Typing indicators are enabled by default in:
        // - CometChatConversations (shows "typing..." in conversation list)
        // - CometChatMessageHeader (shows "typing..." below user name)
        
        let messagesVC = CometChatMessages()
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // Send typing indicator manually
    func startTyping(to receiverUID: String) {
        let typingIndicator = TypingIndicator(
            receiverID: receiverUID,
            receiverType: .user
        )
        CometChat.startTyping(indicator: typingIndicator)
    }
    
    func stopTyping(to receiverUID: String) {
        let typingIndicator = TypingIndicator(
            receiverID: receiverUID,
            receiverType: .user
        )
        CometChat.endTyping(indicator: typingIndicator)
    }
}
Components Used:

User Presence

Display online/offline status for users.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class PresenceViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // User presence is shown automatically in:
        // - CometChatConversations (green dot for online users)
        // - CometChatMessageHeader (shows "Online" or "Last seen")
        // - CometChatUsers (green dot for online users)
        // - CometChatGroupMembers (green dot for online members)
        
        let conversations = CometChatConversations()
        
        // To hide user status:
        // conversations.hideUserStatus = true
        
        navigationController?.pushViewController(conversations, animated: true)
    }
    
    // Listen for presence changes
    func listenForPresenceChanges() {
        CometChat.addUserListener("presence-listener", self)
    }
}

extension PresenceViewController: CometChatUserDelegate {
    func onUserOnline(user: User) {
        print("\(user.name ?? "") is now online")
    }
    
    func onUserOffline(user: User) {
        print("\(user.name ?? "") went offline")
    }
}

Reactions

Let users react to messages with emojis.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ReactionsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Reactions are enabled by default
        // Users can long-press a message to add reactions
        
        let messagesVC = CometChatMessages()
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // Add reaction programmatically
    func addReaction(to message: BaseMessage, emoji: String) {
        CometChat.addReaction(
            messageId: message.id,
            reaction: emoji
        ) { message in
            print("Reaction added")
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // Remove reaction
    func removeReaction(from message: BaseMessage, emoji: String) {
        CometChat.removeReaction(
            messageId: message.id,
            reaction: emoji
        ) { message in
            print("Reaction removed")
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}

Mentions

Tag users in messages with @mentions.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class MentionsViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Mentions are enabled by default
        // Type @ in the composer to see mention suggestions
        
        let messagesVC = CometChatMessages()
        
        CometChat.getGroup(GUID: "group-123") { group in
            DispatchQueue.main.async {
                messagesVC.set(group: group)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // Send message with mention programmatically
    func sendMessageWithMention(to groupID: String, mentionedUser: User) {
        let textMessage = TextMessage(
            receiverUid: groupID,
            text: "Hey @\(mentionedUser.name ?? ""), check this out!",
            receiverType: .group
        )
        
        // Add mentioned users
        textMessage.mentionedUsers = [mentionedUser]
        
        CometChat.sendTextMessage(message: textMessage) { message in
            print("Message with mention sent")
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}

Threaded Conversations

Reply to specific messages in threads.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ThreadedMessagesViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Threaded messages are enabled by default
        // Users can tap "Reply in thread" on any message
        
        let messagesVC = CometChatMessages()
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // Open thread view for a message
    func openThread(for parentMessage: BaseMessage, user: User) {
        let threadedMessages = CometChatThreadedMessages()
        threadedMessages.set(parentMessage: parentMessage)
        threadedMessages.set(user: user)
        navigationController?.pushViewController(threadedMessages, animated: true)
    }
    
    // Send reply in thread programmatically
    func sendThreadReply(parentMessage: BaseMessage, text: String) {
        let reply = TextMessage(
            receiverUid: parentMessage.receiverUid,
            text: text,
            receiverType: parentMessage.receiverType
        )
        reply.parentMessageId = parentMessage.id
        
        CometChat.sendTextMessage(message: reply) { message in
            print("Thread reply sent")
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}
Component Used:

Group Chat

Create and manage group conversations.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class GroupChatViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        showGroupsList()
    }
    
    // Show all groups
    func showGroupsList() {
        let groups = CometChatGroups()
        
        groups.set(onItemClick: { [weak self] group, _ in
            self?.openGroupChat(group: group)
        })
        
        navigationController?.pushViewController(groups, animated: true)
    }
    
    // Open chat for a group
    func openGroupChat(group: Group) {
        let messagesVC = CometChatMessages()
        messagesVC.set(group: group)
        navigationController?.pushViewController(messagesVC, animated: true)
    }
    
    // Create a new group
    func createGroup(name: String, type: CometChat.groupType) {
        let group = Group(
            guid: UUID().uuidString,
            name: name,
            groupType: type,
            password: nil
        )
        
        CometChat.createGroup(group: group) { createdGroup in
            print("Group created: \(createdGroup.name ?? "")")
            DispatchQueue.main.async {
                self.openGroupChat(group: createdGroup)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
    
    // Join a public group
    func joinGroup(guid: String) {
        CometChat.joinGroup(
            GUID: guid,
            groupType: .public,
            password: nil
        ) { group in
            print("Joined group: \(group.name ?? "")")
            DispatchQueue.main.async {
                self.openGroupChat(group: group)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}
Related Guide: Groups

Quoted Reply

Reply to specific messages with context.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class QuotedReplyViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Quoted reply is enabled by default
        // Users can swipe right on a message or tap "Reply" in message actions
        
        let messagesVC = CometChatMessages()
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}
Search across conversations and messages.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class SearchViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Search is available in:
        // - CometChatConversations (search bar at top)
        // - CometChatMessageHeader (search button)
        
        let conversations = CometChatConversations()
        
        // Search is enabled by default
        // To hide search:
        // conversations.hideSearch = true
        
        navigationController?.pushViewController(conversations, animated: true)
    }
    
    // Open dedicated search screen
    func openSearch() {
        let search = CometChatSearch()
        navigationController?.pushViewController(search, animated: true)
    }
}
Components Used:

Moderation

Automatically filter inappropriate content.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ModerationViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Moderation is handled automatically based on your
        // CometChat dashboard settings
        
        // Blocked messages are displayed appropriately
        // based on your moderation rules
        
        let messagesVC = CometChatMessages()
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}
Configure moderation rules in your CometChat Dashboard.

Report Message

Allow users to report inappropriate messages.
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ReportMessageViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Report message is available in message actions
        // Users can long-press a message and select "Report"
        
        let messagesVC = CometChatMessages()
        
        CometChat.getUser(UID: "user-123") { user in
            DispatchQueue.main.async {
                messagesVC.set(user: user)
                self.navigationController?.pushViewController(messagesVC, animated: true)
            }
        } onError: { error in
            print("Error: \(error?.errorDescription ?? "")")
        }
    }
}
View and manage reported messages in Flagged Messages.

Complete Chat App Example

Here’s a production-ready implementation combining all core features:
import UIKit
import CometChatUIKitSwift
import CometChatSDK

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        // Initialize CometChat
        let uiKitSettings = UIKitSettings()
            .set(appID: "YOUR_APP_ID")
            .set(authKey: "YOUR_AUTH_KEY")
            .set(region: "YOUR_REGION")
            .build()
        
        CometChatUIKit.init(uiKitSettings: uiKitSettings) { result in
            switch result {
            case .success:
                self.loginAndShowChat()
            case .failure(let error):
                print("Init failed: \(error.localizedDescription)")
            }
        }
        
        return true
    }
    
    private func loginAndShowChat() {
        CometChatUIKit.login(uid: "user-123") { result in
            switch result {
            case .success(let user):
                print("Logged in as: \(user.name ?? "")")
                DispatchQueue.main.async {
                    self.showMainScreen()
                }
            case .failure(let error):
                print("Login failed: \(error.localizedDescription)")
            }
        }
    }
    
    private func showMainScreen() {
        let tabBar = MainTabBarController()
        window?.rootViewController = tabBar
        window?.makeKeyAndVisible()
    }
}

class MainTabBarController: UITabBarController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Conversations Tab
        let conversationsNav = UINavigationController()
        let conversations = CometChatConversations()
        conversations.set(onItemClick: { [weak conversationsNav] conversation, _ in
            let messagesVC = CometChatMessages()
            if let user = conversation.conversationWith as? User {
                messagesVC.set(user: user)
            } else if let group = conversation.conversationWith as? Group {
                messagesVC.set(group: group)
            }
            conversationsNav?.pushViewController(messagesVC, animated: true)
        })
        conversationsNav.setViewControllers([conversations], animated: false)
        conversationsNav.tabBarItem = UITabBarItem(
            title: "Chats",
            image: UIImage(systemName: "message"),
            selectedImage: UIImage(systemName: "message.fill")
        )
        
        // Users Tab
        let usersNav = UINavigationController()
        let users = CometChatUsers()
        users.set(onItemClick: { [weak usersNav] user, _ in
            let messagesVC = CometChatMessages()
            messagesVC.set(user: user)
            usersNav?.pushViewController(messagesVC, animated: true)
        })
        usersNav.setViewControllers([users], animated: false)
        usersNav.tabBarItem = UITabBarItem(
            title: "Users",
            image: UIImage(systemName: "person.2"),
            selectedImage: UIImage(systemName: "person.2.fill")
        )
        
        // Groups Tab
        let groupsNav = UINavigationController()
        let groups = CometChatGroups()
        groups.set(onItemClick: { [weak groupsNav] group, _ in
            let messagesVC = CometChatMessages()
            messagesVC.set(group: group)
            groupsNav?.pushViewController(messagesVC, animated: true)
        })
        groupsNav.setViewControllers([groups], animated: false)
        groupsNav.tabBarItem = UITabBarItem(
            title: "Groups",
            image: UIImage(systemName: "person.3"),
            selectedImage: UIImage(systemName: "person.3.fill")
        )
        
        viewControllers = [conversationsNav, usersNav, groupsNav]
    }
}

Feature Summary

FeatureComponentEnabled by Default
Text MessagingMessages
Media SharingMessageComposer
Read ReceiptsMessageList
Typing IndicatorsMessageHeader
User PresenceConversations
ReactionsMessageList
MentionsMessageComposer
ThreadsThreadedMessages
SearchSearch
ModerationDashboard ConfigConfigure in Dashboard