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

# Threaded Messages

> Send, receive, and fetch CometChat threaded messages in iOS conversations using parent message IDs.

<Accordion title="AI Integration Quick Reference">
  ```swift theme={null}
  // Send message in a thread
  let msg = TextMessage(receiverUid: "UID", text: "Reply", receiverType: .user)
  msg.parentMessageId = 100
  CometChat.sendTextMessage(message: msg, onSuccess: { _ in }, onError: { _ in })

  // Fetch thread messages
  let threadRequest = MessagesRequest.MessageRequestBuilder()
    .setParentMessageId(parentMessageId: 100).set(limit: 30).build()
  threadRequest.fetchPrevious(onSuccess: { _ in }, onError: { _ in })

  // Exclude thread replies from main conversation
  let mainRequest = MessagesRequest.MessageRequestBuilder()
    .set(uid: "UID").set(limit: 30).hideReplies(hide: true).build()
  ```
</Accordion>

Threaded messages (or threads) are messages started from a particular parent message. Each thread is attached to a parent message.

## Send Message in a Thread

Any message type (Text, Media, or Custom) can be sent in a thread. Set the `parentMessageId` property to indicate which thread the message belongs to.

### Send Text Message in Thread

```swift theme={null}
let receiverID = "cometchat-uid-2"
let text = "Hello"

let textMessage = TextMessage(receiverUid: receiverID, text: text, receiverType: .user)
textMessage.parentMessageId = 38208

CometChat.sendTextMessage(message: textMessage, onSuccess: { (message) in
  print("TextMessage sent successfully. " + message.stringValue())
}) { (error) in
  print("TextMessage sending failed with error: " + error!.errorDescription);
}
```

### Send Media Message in Thread

```swift theme={null}
let receiverID = "cometchat-uid-2"
let fileUrl = "https://data-us.cometchat.io/assets/images/avatars/ironman.png"

let mediaMessage = MediaMessage(receiverUid: receiverID, fileurl: fileUrl, messageType: .image, receiverType: .user)
mediaMessage.parentMessageId = 38208

CometChat.sendMediaMessage(message: mediaMessage, onSuccess: { (message) in
  print("MediaMessage sent successfully. " + message.stringValue())
}) { (error) in
  print("MediaMessage sending failed with error: " + error!.errorDescription);
}
```

### Send Custom Message in Thread

```swift theme={null}
let receiverID = "cometchat-uid-2"
let customData: [String: Any] = ["emoji": "👍", "replyType": "reaction"]

let customMessage = CustomMessage(receiverUid: receiverID, receiverType: .user, customData: customData, type: "thread_reaction")
customMessage.parentMessageId = 38208

CometChat.sendCustomMessage(message: customMessage, onSuccess: { (message) in
  print("CustomMessage sent successfully. " + message.stringValue())
}) { (error) in
  print("CustomMessage sending failed with error: " + error!.errorDescription);
}
```

## Receiving Real-Time Messages

Use `CometChatMessageDelegate` to receive real-time thread messages. Check if the received message belongs to the active thread using `parentMessageId`.

```swift theme={null}
var activeThreadId = 38208

extension ViewController: CometChatMessageDelegate {

  func onTextMessageReceived(textMessage: TextMessage) {
    if textMessage.parentMessageId == activeThreadId {
      print("TextMessage received in thread: " + textMessage.stringValue())
    }
  }

  func onMediaMessageReceived(mediaMessage: MediaMessage) {
    if mediaMessage.parentMessageId == activeThreadId {
      print("MediaMessage received in thread: " + mediaMessage.stringValue())
    }
  }

  func onCustomMessageReceived(customMessage: CustomMessage) {
    if customMessage.parentMessageId == activeThreadId {
      print("CustomMessage received in thread: " + customMessage.stringValue())
    }
  }
}
```

## Fetch all the messages for any particular thread

Use `MessagesRequestBuilder` with `setParentMessageId()` to fetch messages belonging to a specific thread. The `fetchPrevious()` method returns an array of [`BaseMessage`](/sdk/reference/messages#basemessage) objects representing thread replies.

```swift theme={null}
let messagesRequest = MessagesRequest.MessageRequestBuilder()
  .setParentMessageId(parentMessageId: 38208)
  .set(limit: 50)
  .build()

messagesRequest.fetchPrevious(onSuccess: { (messages) in
  for message in messages! {
    if let textMessage = message as? TextMessage {
      print("Text Message: " + textMessage.stringValue())
    } else if let mediaMessage = message as? MediaMessage {
      print("Media Message: " + mediaMessage.stringValue())
    } else if let customMessage = message as? CustomMessage {
      print("Custom Message: " + customMessage.stringValue())
    }
  }
}) { (error) in
  print("Messages fetching failed with error: " + error!.errorDescription)
}
```

## Avoid Threaded Messages in User/Group Conversations

Use `hideReplies(hide: true)` to exclude threaded messages when fetching messages for a conversation. The response is an array of [`BaseMessage`](/sdk/reference/messages#basemessage) objects, excluding any messages that are replies within a thread.

<Tabs>
  <Tab title="Swift (User)">
    ```swift theme={null}
    let messagesRequest = MessagesRequest.MessageRequestBuilder()
      .set(uid: "cometchat-uid-2")
      .set(limit: 50)
      .hideReplies(hide: true)
      .build()

    messagesRequest.fetchPrevious(onSuccess: { (messages) in
      for message in messages! {
        print("Message ID: \(message.id), parentMessageId: \(message.parentMessageId)")
      }
    }) { (error) in
      print("Messages fetching failed with error: " + error!.errorDescription)
    }
    ```
  </Tab>

  <Tab title="Swift (Group)">
    ```swift theme={null}
    let messagesRequest = MessagesRequest.MessageRequestBuilder()
      .set(guid: "cometchat-guid-1")
      .set(limit: 50)
      .hideReplies(hide: true)
      .build()

    messagesRequest.fetchPrevious(onSuccess: { (messages) in
      for message in messages! {
        print("Message ID: \(message.id), parentMessageId: \(message.parentMessageId)")
      }
    }) { (error) in
      print("Messages fetching failed with error: " + error!.errorDescription)
    }
    ```
  </Tab>
</Tabs>

***

## Next Steps

<CardGroup cols={2}>
  <Card title="Send Messages" icon="paper-plane" href="/sdk/ios/send-message">
    Send text, media, and custom messages to users and groups
  </Card>

  <Card title="Receive Messages" icon="inbox" href="/sdk/ios/receive-message">
    Listen for incoming messages in real-time and fetch missed messages
  </Card>

  <Card title="Reactions" icon="face-smile" href="/sdk/ios/reactions">
    Add emoji reactions to messages
  </Card>

  <Card title="Message Filtering" icon="filter" href="/sdk/ios/additional-message-filtering">
    Advanced message filtering with RequestBuilder
  </Card>
</CardGroup>
