Skip to main content
Enhance your iOS chat app with threaded messaging by integrating CometChat’s UIKit for iOS, allowing users to reply to specific messages within a focused thread view.

Overview

Threaded messages allow users to reply to specific messages within a conversation, creating a sub-conversation for improved clarity and context. With CometChat’s UIKit for iOS, you can:
  • Display a dedicated thread view
  • View and send replies to a selected message
  • Maintain context between the main conversation and the thread

Prerequisites

Before implementing threaded messages, ensure you have:
  • Completed Getting Started setup
  • CometChat UIKit v4+ installed via Swift Package Manager or CocoaPods
  • Valid CometChat App ID, Region, and Auth Key
  • A navigation controller configured in your project

Components

ComponentDescription
CometChatMessageListDisplays messages and provides onThreadRepliesClick handler
CometChatThreadedMessageHeaderShows the parent message context at the top of the thread
CometChatMessageComposerComposes messages with an optional parentMessageId
ThreadedMessagesVCView controller that hosts the threaded conversation

Integration Steps

Step 1: Show the “Reply in Thread” Option

Navigate to the thread when a message’s thread icon is tapped:
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class MessagesViewController: UIViewController {
    
    var messageListView: CometChatMessageList!
    
    func setupThreadReplies() {
        // Handle thread replies click
        messageListView.set(onThreadRepliesClick: { [weak self] message, _ in
            guard let self = self else { return }
            
            // Create and configure thread view controller
            let threadVC = ThreadedMessagesVC()
            threadVC.parentMessage = message
            
            // Navigate to thread screen
            self.navigationController?.pushViewController(threadVC, animated: true)
        })
    }
}
This captures user intent and opens a focused thread screen. File reference: ThreadedMessagesVC.swift

Step 2: Navigate to the Thread Screen

Show a dedicated UI for thread replies. In ThreadedMessagesVC.swift:
import UIKit
import CometChatUIKitSwift
import CometChatSDK

class ThreadedMessagesVC: UIViewController {
    
    var parentMessage: BaseMessage?
    var user: User?
    var group: Group?
    
    private var parentMessageContainerView: CometChatThreadedMessageHeader!
    private var messageListView: CometChatMessageList!
    private var composerView: CometChatMessageComposer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        setupUI()
    }
    
    private func setupUI() {
        // Add UI components to view hierarchy
        view.addSubview(parentMessageView)
        view.addSubview(messageListView)
        view.addSubview(composerView)
    }
}
Header configuration:
// Create the threaded message header
let parentMessageContainerView = CometChatThreadedMessageHeader()
Message list configuration:
// Configure message list with user and parent message
messageListView.set(user: user, parentMessage: parentMessage)
This provides a focused UI for thread interactions.

Step 3: Send a Threaded Message

Ensure new replies are attached to the correct parent message:
// Set the parent message ID for threaded replies
composerView.set(parentMessageId: parentMessage?.id ?? 0)
Set the conversation context:
// Configure composer for user conversation
composerView.set(user: user)

// Or configure for group conversation
composerView.set(group: group)

Step 4: Fetch and Display Thread Replies

Only messages that are part of the thread are displayed. This is handled internally by:
// Configure message list to fetch thread replies
messageListView.set(user: user, parentMessage: parentMessage)
This ensures CometChatMessageList fetches replies using the parentMessageId.

Customization Options

Header Styling

Customize CometChatThreadedMessageHeader appearance:
// Customize fonts, colors, and layout
let headerStyle = ThreadedMessageHeaderStyle()
headerStyle.titleFont = UIFont.systemFont(ofSize: 16, weight: .semibold)
headerStyle.titleColor = .label
parentMessageContainerView.set(style: headerStyle)

Composer

Modify placeholder text, input styles, and icons:
// Customize composer appearance
composerView.set(placeholderText: "Reply in thread...")
Add a custom back button for navigation:
// Add custom back button
navigationItem.leftBarButtonItem = UIBarButtonItem(
    image: UIImage(systemName: "chevron.left"),
    style: .plain,
    target: self,
    action: #selector(goBack)
)

Edge Cases

ScenarioHandling
Parent message deletedDisplay a fallback UI or disable the composer
No repliesShow an empty state (e.g., “No replies yet”)
Offline modeDisable the composer and queue thread operations

Error Handling

Error TypeSolution
Fetch failuresShow an error UI or retry mechanism when loading thread messages
Send failuresHandle send errors via delegate callbacks or show an alert with retry
Loading statesDisplay a UIActivityIndicatorView during fetch/send operations
Blocked usersRemove the composer and display a blocked status label

Feature Matrix

FeatureImplementation
Show thread optionCometChatMessageList.onThreadRepliesClick
Thread view screenThreadedMessagesVC.swift
Display threaded messagesCometChatMessageList.set(parentMessage:)
Send threaded messageCometChatMessageComposer.set(parentMessageId:)
Thread headerCometChatThreadedMessageHeader
Handle blocked userRemove composer and show a blocked user label