Skip to main content
The CometChatSearch component is a powerful and customizable search interface that allows users to search across conversations and messages in real time. It supports a wide variety of filters, scopes, and customization options.
{
  "component": "CometChatSearch",
  "package": "CometChatUIKitSwift",
  "import": "import CometChatUIKitSwift\nimport CometChatSDK",
  "description": "Provides search functionality across conversations and messages",
  "inherits": "UIViewController",
  "primaryOutput": {
    "callback": "onMessageClicked",
    "type": "(BaseMessage) -> Void"
  },
  "props": {
    "callbacks": {
      "onConversationClicked": "(Conversation) -> Void",
      "onMessageClicked": "(BaseMessage) -> Void",
      "onBack": "() -> Void",
      "onError": "(CometChatException) -> Void"
    },
    "visibility": {
      "hideNavigationBar": { "type": "Bool", "default": false }
    }
  },
  "events": [],
  "sdkListeners": [],
  "compositionExample": {
    "description": "Search is typically accessed from conversation list or message header",
    "components": ["CometChatConversations", "CometChatSearch", "CometChatMessages"],
    "flow": "User taps search → enters query → taps result → navigates to conversation/message"
  }
}

Usage

Integration

CometChatSearch is a composite component that offers flexible integration options. It can be launched directly via button clicks or any user-triggered action.
let search = CometChatSearch()
self.navigationController?.pushViewController(search, animated: true)

Actions

Actions dictate how a component functions. They are divided into two types: Predefined and User-defined. You can override either type to tailor the behavior to fit your specific needs.

1. onConversationClicked

Triggered when you click on a Conversation from the search result. This action doesn’t have a predefined behavior—you can override it using the following code snippet:
search.onConversationClicked = { conversation in
    print("Conversation clicked:", conversation.conversationId)
}

2. onMessageClicked

Triggered when you click on a Message from the search result. This action doesn’t have a predefined behavior—you can override it using the following code snippet:
search.onMessageClicked = { message in
    print("Message clicked:", message.id)
}

3. onBack

Triggered when you click on the back button of the search component.
search.onBack = {
    self.navigationController?.popViewController(animated: true)
}

4. onError

Listens for any errors that occur in the Search component. This action doesn’t change the component’s behavior.
search.set(onError: { error in
    print("Search error:", error.localizedDescription)
})

5. onEmpty

Listens for the empty state of the Search component. This action doesn’t change the component’s behavior.
search.set(onEmpty: {
    print("No results found")
})

Filters

Filters allow you to customize the data displayed in a list within a Component. You can filter the list based on your specific criteria using RequestBuilders of the Chat SDK.

SearchScope

The SearchScope enum defines what types of content to search:
ValueDescription
.conversationsSearch in conversations
.messagesSearch in messages
// Search only in messages
search.set(searchIn: [.messages])

// Search in both conversations and messages (default)
search.set(searchIn: [.conversations, .messages])

SearchFilter

The SearchFilter enum defines available filter options:
ValueDescription
.unreadFilter by unread items
.groupsFilter by group conversations
.photosFilter by photo messages
.videosFilter by video messages
.linksFilter by link messages
.documentsFilter by document messages
.audioFilter by audio messages
// Set available filters with an initial selection
search.set(searchFilters: [.unread, .groups, .photos, .videos], initialFilter: .photos)

1. ConversationsRequestBuilder

Set the ConversationsRequestBuilder in the Search Component to filter the search results. For more options, refer to ConversationRequestBuilder.
let convBuilder = ConversationsRequest.ConversationsRequestBuilder()
    .set(limit: 20)

search.set(conversationsRequestBuilder: convBuilder)

2. MessagesRequestBuilder

Set the MessagesRequestBuilder in the Search Component to filter the search results. For more options, refer to MessagesRequestBuilder.
let msgBuilder = MessagesRequest.MessageRequestBuilder()
    .set(limit: 30)
    .hide(deletedMessages: true)

search.set(messagesRequestBuilder: msgBuilder)

Events

Events are emitted by a Component. By using events, you can extend existing functionality. Being global events, they can be applied in multiple locations and can be added or removed as needed. The CometChatSearch component does not produce any events.

Customization

To fit your app’s design requirements, you can customize the appearance of the CometChatSearch component. We provide exposed methods that allow you to modify the experience and behavior according to your specific needs.

Style

Using Style, you can customize the look and feel of the component in your app. These parameters typically control elements such as the color, size, shape, and fonts used within the component.
// Instance-level styling
let style = SearchStyle()
style.backgroundColor = UIColor(hex: "#EDEAFA")
style.listItemBackground = UIColor(hex: "#EDEAFA")
style.listItemTitleFont = UIFont(name: "TimesNewRomanPS-Regular", size: 16)
style.titleFont = UIFont(name: "TimesNewRomanPS-Bold", size: 12)
style.searchBarPlaceholderTextFont = UIFont(name: "TimesNewRomanPS-Regular", size: 12)

let searchVC = CometChatSearch()
searchVC.style = style
self?.navigationController?.pushViewController(searchVC, animated: true)

// Global-level styling
CometChatSearch.style.backgroundColor = UIColor(hex: "#EDEAFA")
CometChatSearch.style.listItemBackground = UIColor(hex: "#EDEAFA")
CometChatSearch.style.listItemTitleFont = UIFont(name: "TimesNewRomanPS-Regular", size: 16)
CometChatSearch.style.titleFont = UIFont(name: "TimesNewRomanPS-Bold", size: 12)
CometChatSearch.style.searchBarPlaceholderTextFont = UIFont(name: "TimesNewRomanPS-Regular", size: 12)

Functionality

These are small functional customizations that allow you to fine-tune the overall experience of the component. With these, you can toggle the visibility of UI elements.
PropertyDescriptionExample
userRestrict search to a specific user chatsearch.user = user
groupRestrict search to a groupsearch.group = group
hideUserStatusHide online/offline indicatorsearch.hideUserStatus = true
hideGroupTypeHide group type iconsearch.hideGroupType = true
searchFiltersFilters like “Unread”, “Groups”, “Photos”, etc.search.set(searchFilters: [.unread, .groups, .photos])
initialSearchFilterDefault filter to apply on loadsearch.set(searchFilters: [...], initialFilter: .photos)
searchIn (searchScopes)Restrict search: messages / conversations / bothsearch.set(searchIn: [.messages, .conversations])
loadingViewCustom loader viewsearch.set(loadingView: spinner)
emptyViewCustom empty result viewsearch.set(emptyView: emptyView)
errorViewCustom error UIsearch.set(errorView: errorView)
disableTypingDisable typing indicatorssearch.disableTyping = true
disableSoundForMessagesDisable message soundssearch.disableSoundForMessages = true
customSoundForMessagesCustom sound URL for messagessearch.customSoundForMessages = URL(string: "...")

Advanced

For advanced-level customization, you can set custom views to the component. This lets you tailor each aspect of the component to fit your exact needs and application aesthetics. You can create and define your own views, layouts, and UI elements and then incorporate those into the component.

Conversation View Customization

FunctionDescription
listItemViewForConversationAssign a custom list item view to a conversation.
leadingViewForConversationAssign a custom leading view to a conversation.
titleViewForConversationAssign a custom title view to a conversation.
subtitleViewForConversationAssign a custom subtitle view to a conversation.
tailViewForConversationAssign a custom trailing view to a conversation.
let searchVC = CometChatSearch()

searchVC.set(listItemViewForConversation: { conversation in
    let customView = UIView()
    // Configure custom conversation view
    return customView
})

Message View Customization

With message item view functions, you can assign custom views to different types of messages in the search result. For more information, refer to the itemView prop of the CometChatMessages component. Here’s how you can override the default message item view with a custom one for text messages:
let searchVC = CometChatSearch()
searchVC.set(listItemViewForMessage: { message in
    return SearchMessageItemView()
})
Custom view implementation:
class SearchMessageItemView: UIView {

    // MARK: - UI Components
    
    private let containerView: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(red: 0.95, green: 0.93, blue: 0.98, alpha: 1.0)
        return view
    }()
    
    private let senderLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.boldSystemFont(ofSize: 16)
        label.textColor = UIColor(red: 0.37, green: 0.22, blue: 0.73, alpha: 1.0)
        return label
    }()
    
    private let messageLabel: UILabel = {
        let label = UILabel()
        label.font = UIFont.systemFont(ofSize: 16)
        label.textColor = UIColor.darkGray
        label.numberOfLines = 1
        label.lineBreakMode = .byTruncatingTail
        return label
    }()
    
    private let bottomLine: UIView = {
        let view = UIView()
        view.backgroundColor = UIColor(red: 0.37, green: 0.22, blue: 0.73, alpha: 1.0)
        return view
    }()
    
    private let stack: UIStackView = {
        let stack = UIStackView()
        stack.axis = .horizontal
        stack.spacing = 4
        stack.alignment = .center
        return stack
    }()
    
    // MARK: - Initialization
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupUI()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupUI()
    }
    
    // MARK: - Setup
    
    private func setupUI() {
        addSubview(containerView)
        containerView.translatesAutoresizingMaskIntoConstraints = false
        
        containerView.addSubview(stack)
        stack.translatesAutoresizingMaskIntoConstraints = false
        
        containerView.addSubview(bottomLine)
        bottomLine.translatesAutoresizingMaskIntoConstraints = false
        
        stack.addArrangedSubview(senderLabel)
        stack.addArrangedSubview(messageLabel)

        NSLayoutConstraint.activate([
            containerView.topAnchor.constraint(equalTo: topAnchor),
            containerView.leadingAnchor.constraint(equalTo: leadingAnchor),
            containerView.trailingAnchor.constraint(equalTo: trailingAnchor),
            containerView.bottomAnchor.constraint(equalTo: bottomAnchor),
            
            stack.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 12),
            stack.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 12),
            stack.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -12),
            
            bottomLine.heightAnchor.constraint(equalToConstant: 2),
            bottomLine.leadingAnchor.constraint(equalTo: containerView.leadingAnchor),
            bottomLine.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),
            bottomLine.bottomAnchor.constraint(equalTo: containerView.bottomAnchor)
        ])
    }
    
    // MARK: - Configuration
    
    /// Configure view with sender name and message text
    /// - Parameters:
    ///   - sender: The sender's name
    ///   - message: The message content
    ///   - boldKeyword: Optional keyword to highlight in bold
    func configure(sender: String, message: String, boldKeyword: String?) {
        senderLabel.text = sender + ":"
        
        if let keyword = boldKeyword, message.contains(keyword) {
            let attributed = NSMutableAttributedString(string: message)
            let range = (message as NSString).range(of: keyword)
            attributed.addAttribute(.font, value: UIFont.boldSystemFont(ofSize: 16), range: range)
            messageLabel.attributedText = attributed
        } else {
            messageLabel.text = message
        }
    }
}
Available message item view functions for customization:
FunctionMessage Type
listItemViewForMessageText Message
listItemViewForImageImage Message
listItemViewForVideoVideo Message
listItemViewForAudioAudio Message
listItemViewForDocumentDocument Message
listItemViewForLinkLink Message
let searchVC = CometChatSearch()

// Custom view for image messages
searchVC.set(listItemViewForImage: { mediaMessage in
    let customView = UIView()
    // Configure custom image message view
    return customView
})

// Custom view for video messages
searchVC.set(listItemViewForVideo: { mediaMessage in
    let customView = UIView()
    // Configure custom video message view
    return customView
})

// Custom view for audio messages
searchVC.set(listItemViewForAudio: { mediaMessage in
    let customView = UIView()
    // Configure custom audio message view
    return customView
})

// Custom view for document messages
searchVC.set(listItemViewForDocument: { mediaMessage in
    let customView = UIView()
    // Configure custom document message view
    return customView
})

// Custom view for link messages
searchVC.set(listItemViewForLink: { mediaMessage in
    let customView = UIView()
    // Configure custom link message view
    return customView
})

Mention Configuration

Configure how @all mentions appear in search results using the setMentionAllLabel method.
let searchVC = CometChatSearch()

// Set a custom label for @all mentions
searchVC.setMentionAllLabel("all", "Everyone")

DateTime Formatters

By providing a custom implementation of the DateTimeFormatterCallback, you can configure how time and date values are displayed. This ensures consistent formatting for labels such as “Today”, “Yesterday”, “X minutes ago”, and more.
let searchVC = CometChatSearch()

searchVC.dateTimeFormatter.today = { timestamp in
    return "Today • \(formattedTime(timestamp))"
}

searchVC.dateTimeFormatter.otherDay = { timestamp in
    let df = DateFormatter()
    df.dateFormat = "dd MMM yyyy"
    return df.string(from: Date(timeIntervalSince1970: timestamp))
}

Text Formatters

The setTextFormatters method enables developers to define and apply text formatters that dynamically modify or transform message content before rendering it in the UI. Text formatters can be used for:
  • Automatically converting URLs into clickable links
  • Applying Markdown or rich text styling
  • Replacing certain words or patterns with emojis or predefined text
  • Censoring specific words for moderation
By utilizing this method, developers can enhance readability, usability, and compliance with content guidelines. See the MentionsFormatter Guide for more details.