Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion docs.json
Original file line number Diff line number Diff line change
Expand Up @@ -1496,6 +1496,8 @@
"ui-kit/ios/message-composer",
"ui-kit/ios/compact-message-composer",
"ui-kit/ios/threaded-messages-header",
"ui-kit/ios/pinned-messages",
"ui-kit/ios/saved-messages",
"ui-kit/ios/incoming-call",
"ui-kit/ios/outgoing-call",
"ui-kit/ios/ongoing-call",
Expand Down Expand Up @@ -1526,6 +1528,8 @@
"pages": [
"ui-kit/ios/guide-overview",
"ui-kit/ios/guide-threaded-messages",
"ui-kit/ios/guide-thread-subscription",
"ui-kit/ios/guide-pin-save-message",
"ui-kit/ios/guide-block-unblock-user",
"ui-kit/ios/guide-new-chat",
"ui-kit/ios/guide-message-privately",
Expand Down Expand Up @@ -3846,6 +3850,7 @@
"sdk/ios/additional-message-filtering",
"sdk/ios/retrieve-conversations",
"sdk/ios/threaded-messages",
"sdk/ios/thread-subscription",
"sdk/ios/edit-message",
"sdk/ios/delete-message",
"sdk/ios/delete-conversation",
Expand All @@ -3854,7 +3859,8 @@
"sdk/ios/transient-messages",
"sdk/ios/delivery-read-receipts",
"sdk/ios/mentions",
"sdk/ios/reactions"
"sdk/ios/reactions",
"sdk/ios/pin-save-message"
]
},
"sdk/ios/calling-overview",
Expand Down
6 changes: 5 additions & 1 deletion sdk/ios/additional-message-filtering.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,17 @@ Use `setTags()` with an array of tag names to fetch only messages with those tag

```swift
var limit = 30
let tags = ["pinned"]
let tags = ["important"]
let messagesRequest = MessagesRequest.MessageRequestBuilder()
.setLimit(50)
.setTags(tags)
.build()
```

<Note>
To fetch pinned or saved messages, filter with `set(pinned:)` or `set(saved:)` rather than tags — see [Pin & Save Messages](/sdk/ios/pin-save-message).
</Note>

---

## Next Steps
Expand Down
4 changes: 4 additions & 0 deletions sdk/ios/all-real-time-delegates-listeners.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -95,13 +95,13 @@

| Method | Information |
| ------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
| **onGroupMemberJoined(action:** [`Action`](/sdk/reference/messages#action)**, joinedUser:** [`User`](/sdk/reference/entities#user)**, joinedGroup:** [`Group`](/sdk/reference/entities#group)**)** | This method is triggered when a user joins any group. All the members present in the group will receive this event. |

Check warning on line 98 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L98

Did you really mean 'joinedUser'?

Check warning on line 98 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L98

Did you really mean 'joinedGroup'?
| **onGroupMemberLeft(action:** [`Action`](/sdk/reference/messages#action)**, leftUser:** [`User`](/sdk/reference/entities#user)**, leftGroup:** [`Group`](/sdk/reference/entities#group)**)** | This method is triggered when a user who was a member of any group leaves the group. All the members of the group receive this event. |

Check warning on line 99 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L99

Did you really mean 'leftUser'?

Check warning on line 99 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L99

Did you really mean 'leftGroup'?
| **onGroupMemberKicked(action:** [`Action`](/sdk/reference/messages#action)**, kickedUser:** [`User`](/sdk/reference/entities#user)**, kickedBy:** [`User`](/sdk/reference/entities#user)**, kickedFrom:** [`Group`](/sdk/reference/entities#group)**)** | This method is triggered when a user is kicked from a group. All the members including the user receive this event |

Check warning on line 100 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L100

Did you really mean 'kickedUser'?

Check warning on line 100 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L100

Did you really mean 'kickedBy'?

Check warning on line 100 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L100

Did you really mean 'kickedFrom'?
| **onGroupMemberBanned(action:** [`Action`](/sdk/reference/messages#action)**, bannedUser:** [`User`](/sdk/reference/entities#user)**, bannedBy:** [`User`](/sdk/reference/entities#user)**, bannedFrom:** [`Group`](/sdk/reference/entities#group)**)** | This method is triggered when a user is banned from a group. All the members including the user receive this event |

Check warning on line 101 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L101

Did you really mean 'bannedUser'?

Check warning on line 101 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L101

Did you really mean 'bannedBy'?

Check warning on line 101 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L101

Did you really mean 'bannedFrom'?
| **onGroupMemberUnbanned(action:** [`Action`](/sdk/reference/messages#action)**, unbannedUser:** [`User`](/sdk/reference/entities#user)**, unbannedBy:** [`User`](/sdk/reference/entities#user)**, unbannedFrom:** [`Group`](/sdk/reference/entities#group)**)** | This method is triggered when a user is banned from a group. All the members of the group receive this event. |

Check warning on line 102 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L102

Did you really mean 'unbannedUser'?

Check warning on line 102 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L102

Did you really mean 'unbannedBy'?

Check warning on line 102 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L102

Did you really mean 'unbannedFrom'?
| **onGroupMemberScopeChanged(action:** [`Action`](/sdk/reference/messages#action)**, updatedBy:** [`User`](/sdk/reference/entities#user)**, updatedUser:** [`User`](/sdk/reference/entities#user)**, scopeChangedTo: String, scopeChangedFrom: String, group:** [`Group`](/sdk/reference/entities#group)**)** | This method is triggered when the scope of any Group Member has been changed. All the members that are a part of that group receive this event |

Check warning on line 103 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L103

Did you really mean 'updatedBy'?

Check warning on line 103 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L103

Did you really mean 'updatedUser'?
| **onMemberAddedToGroup(action:** [`Action`](/sdk/reference/messages#action)**, addedby:** [`User`](/sdk/reference/entities#user)**, userAdded:** [`User`](/sdk/reference/entities#user)**, addedTo:** [`Group`](/sdk/reference/entities#group)**)** | This method is triggered when a user is added to any group. All the members including the user himself receive this event. |

Check warning on line 104 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L104

Did you really mean 'addedby'?

Check warning on line 104 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L104

Did you really mean 'userAdded'?

Check warning on line 104 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L104

Did you really mean 'addedTo'?

You can receive live events related to groups. In order to receive group events, you must add protocol conformance `CometChatGroupDelegate` as shown below:

Expand All @@ -114,23 +114,23 @@
print("\\(joinedUser.name) joined the group \\(joinedGroup.name).")
}

func onGroupMemberLeft(action: ActionMessage, leftUser: User, leftGroup: Group) {

Check warning on line 117 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L117

Did you really mean 'leftUser'?

Check warning on line 117 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L117

Did you really mean 'leftGroup'?
print("\\(leftUser.name) left the group \\(leftGroup.name).")
}

func onGroupMemberKicked(action: ActionMessage, kickedUser: User, kickedBy: User, kickedFrom: Group) {

Check warning on line 121 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L121

Did you really mean 'kickedUser'?

Check warning on line 121 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L121

Did you really mean 'kickedBy'?

Check warning on line 121 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L121

Did you really mean 'kickedFrom'?
print("\\(kickedUser.name) kicked from the group \\(kickedFrom.name) by \\(kickedBy.name).")
}

func onGroupMemberBanned(action: ActionMessage, bannedUser: User, bannedBy: User, bannedFrom: Group) {

Check warning on line 125 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L125

Did you really mean 'bannedUser'?

Check warning on line 125 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L125

Did you really mean 'bannedBy'?

Check warning on line 125 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L125

Did you really mean 'bannedFrom'?
print("\\(bannedUser.name) banned from the group \\(bannedFrom.name) by \\(bannedBy.name).")
}

func onGroupMemberUnbanned(action: ActionMessage, unbannedUser: User, unbannedBy: User, unbannedFrom: Group) {

Check warning on line 129 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L129

Did you really mean 'unbannedUser'?

Check warning on line 129 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L129

Did you really mean 'unbannedBy'?

Check warning on line 129 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L129

Did you really mean 'unbannedFrom'?
print("\\(unbannedUser.name) unbanned from the group \\(unbannedFrom.name) by \\(unbannedBy.name).")
}

func onGroupMemberScopeChanged(action: ActionMessage, scopeChangeduser: User, scopeChangedBy: User, scopeChangedTo: String, scopeChangedFrom: String, group: Group) {

Check warning on line 133 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L133

Did you really mean 'scopeChangeduser'?
print("\\(scopeChangedUser.name) scope changed from \\(scopeChangedFrom) to \\(scopeChangedTo) by \\(scopeChangedBy.name) in the group \\(group.name).")
}
}
Expand Down Expand Up @@ -199,8 +199,8 @@
| **onTextMessageReceived(textMessage:** [`TextMessage`](/sdk/reference/messages#textmessage)**)** | This event is triggered when a Text Message is received. |
| **onMediaMessageReceived(mediaMessage:** [`MediaMessage`](/sdk/reference/messages#mediamessage)**)** | This event is triggered when a Media Message is received. |
| **onCustomMessageReceived(customMessage:** [`CustomMessage`](/sdk/reference/messages#custommessage)**)** | This event is triggered when a Custom Message is received. |
| **onTypingStarted(_ typingDetails:** [`TypingIndicator`](/sdk/reference/auxiliary#typingindicator)**)** | This event is triggered when a user starts typing in a user/group conversation. |

Check warning on line 202 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L202

Did you really mean 'typingDetails'?
| **onTypingEnded(_ typingDetails:** [`TypingIndicator`](/sdk/reference/auxiliary#typingindicator)**)** | This event is triggered when a user stops typing in a user/group conversation. |

Check warning on line 203 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L203

Did you really mean 'typingDetails'?
| **onTransisentMessageReceived(_ message:** [`TransientMessage`](/sdk/reference/auxiliary#transientmessage)**)** | This event is triggered when a transient message is received. |
| **onMessagesDelivered(receipt:** [`MessageReceipt`](/sdk/reference/auxiliary#messagereceipt)**)** | This event is triggered when a set of messages are marked as delivered for any particular conversation. |
| **onMessagesRead(receipt:** [`MessageReceipt`](/sdk/reference/auxiliary#messagereceipt)**)** | This event is triggered when a set of messages are marked as read for any particular conversation. |
Expand All @@ -212,6 +212,10 @@
| **onInteractionGoalCompleted(_ receipt: InteractionReceipt)**| This event is triggered when an interaction Goal is achieved. |
| **onMessageReactionAdded(reactionEvent: ReactionEvent)** | This event is triggered when a reaction is added to a message. |
| **onMessageReactionRemoved(reactionEvent: ReactionEvent)** | This event is triggered when a reaction is removed from a message. |
| **onMessagePinned(message:** [`BaseMessage`](/sdk/reference/messages#basemessage)**)** | This event is triggered when a message is pinned. Broadcast to everyone in the conversation. See [Pin & Save Messages](/sdk/ios/pin-save-message). |
| **onMessageUnpinned(message:** [`BaseMessage`](/sdk/reference/messages#basemessage)**)** | This event is triggered when a message is unpinned. Broadcast to everyone in the conversation. |
| **onMessageSaved(message:** [`BaseMessage`](/sdk/reference/messages#basemessage)**)** | This event is triggered when a message is saved. Private — reaches only the saving user's other devices. |
| **onMessageUnsaved(message:** [`BaseMessage`](/sdk/reference/messages#basemessage)**)** | This event is triggered when a message is unsaved. Private — reaches only the saving user's other devices. |
| **onMessageModerated(_ message:** [`BaseMessage`](/sdk/reference/messages#basemessage)**)** | This event is triggered when a message is moderated. |
| **onAIAssistantMessageReceived(_ message: AIAssistantMessage)** | This event is triggered when an AI Assistant message is received. |
| **onAIToolResultMessageReceived(_ message: AIToolResultMessage)** | This event is triggered when an AI Tool result message is received. |
Expand Down Expand Up @@ -244,11 +248,11 @@
print("Message deleted successfully.")
}

func onTypingStarted(_ typingDetails: TypingIndicator) {

Check warning on line 251 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L251

Did you really mean 'typingDetails'?
print("Typing started received successfully")
}

func onTypingEnded(_ typingDetails: TypingIndicator) {

Check warning on line 255 in sdk/ios/all-real-time-delegates-listeners.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/all-real-time-delegates-listeners.mdx#L255

Did you really mean 'typingDetails'?
print("Typing ended received successfully")
}

Expand Down
308 changes: 308 additions & 0 deletions sdk/ios/pin-save-message.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,308 @@
---
title: "Pin & Save Messages"
sidebarTitle: "Pin & Save Messages"
description: "Pin messages for everyone in a conversation and save messages privately using the CometChat iOS SDK, including message fields, fetching, and listener events."
---

<Accordion title="AI Integration Quick Reference">

```swift
// Pin a message for everyone in the conversation
CometChat.pinMessage(messageId: 148) { msg in } onError: { err in }
CometChat.unpinMessage(messageId: 148) { msg in } onError: { err in }

// Save a message privately for the logged-in user
CometChat.saveMessage(messageId: 148) { msg in } onError: { err in }
CometChat.unsaveMessage(messageId: 148) { msg in } onError: { err in }

// Presence of the timestamp IS the boolean
let isPinned = message.pinnedAt != 0
let isSaved = message.savedAt != 0

// Fetch pinned messages in a conversation
MessagesRequest.MessageRequestBuilder().set(guid: "guid").set(pinned: true).set(limit: 100).build()

// Fetch the user's saved messages across all conversations
MessagesRequest.MessageRequestBuilder().set(saved: true).set(limit: 100).build()

// Listen for events (CometChatMessageDelegate)
func onMessagePinned(message: BaseMessage) { }
func onMessageUnpinned(message: BaseMessage) { }
func onMessageSaved(message: BaseMessage) { }
func onMessageUnsaved(message: BaseMessage) { }
```
</Accordion>

Pin and save let users mark messages for later. The two features look similar but differ in who sees the result:

| | Pin | Save |
|---|---|---|
| Visibility | Everyone in the conversation | Private to the user |
| Scope | One conversation | All conversations |
| Permission | Group owner, admin or moderator | Anyone |
| Limit | 100 per conversation | 100 per user |

---

## Pin a Message

Pinning is conversation-wide: every participant sees the message as pinned.

<Tabs>
<Tab title="Swift">
```swift
CometChat.pinMessage(messageId: 148) { message in
print("Pinned at: \(message.pinnedAt) by \(message.pinnedBy)")
} onError: { error in

Check warning on line 56 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L56

Did you really mean 'onError'?
print("Error: \(error.errorDescription)")
}
```
</Tab>
</Tabs>

<Note>
Pinning is permission-gated. In a group, only the owner, admins and moderators can pin or unpin; everyone can view the pinned list. In one-to-one conversations both participants can pin.
</Note>

---

## Unpin a Message

<Tabs>
<Tab title="Swift">
```swift
CometChat.unpinMessage(messageId: 148) { message in
// pinnedAt is cleared back to 0
print("Unpinned: \(message.pinnedAt == 0)")
} onError: { error in

Check warning on line 77 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L77

Did you really mean 'onError'?
print("Error: \(error.errorDescription)")
}
```
</Tab>
</Tabs>

---

## Save a Message

Saving is private to the logged-in user and syncs across that user's own devices. It carries no permission checks.

<Tabs>
<Tab title="Swift">
```swift
CometChat.saveMessage(messageId: 148) { message in
print("Saved at: \(message.savedAt)")
} onError: { error in

Check warning on line 95 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L95

Did you really mean 'onError'?
print("Error: \(error.errorDescription)")
}
```
</Tab>
</Tabs>

---

## Unsave a Message

Check warning on line 104 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L104

Did you really mean 'Unsave'?

<Tabs>
<Tab title="Swift">
```swift
CometChat.unsaveMessage(messageId: 148) { message in
print("Unsaved: \(message.savedAt == 0)")
} onError: { error in

Check warning on line 111 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L111

Did you really mean 'onError'?
print("Error: \(error.errorDescription)")
}
```
</Tab>
</Tabs>

All four methods return the updated [`BaseMessage`](/sdk/reference/messages#basemessage).

---

## Message Fields

Three fields on `BaseMessage` carry the state:

| Field | Type | Scope | Description |
|-------|------|-------|-------------|
| `pinnedAt` | `Double` | Global | When the message was pinned. `0` when not pinned. |
| `pinnedBy` | `String` | Global | UID of the last user to pin it. `app_system` for a system pin. |
| `savedAt` | `Double` | Per-viewer | When the logged-in user saved it. `0` when not saved. |

<Warning>
**Presence of the timestamp is the boolean.** There is no separate `isPinned` flag — check `pinnedAt != 0` and `savedAt != 0`. Unpinning and unsaving clear the field back to `0` rather than leaving a stale value.

Check warning on line 133 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L133

Did you really mean 'unsaving'?

`savedAt` is per-viewer: it is only ever populated for the user who saved the message, so you cannot use it to tell whether someone else saved it.
</Warning>

<Tabs>
<Tab title="Swift">
```swift
let isPinned = message.pinnedAt != 0

Check warning on line 141 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L141

Did you really mean 'isPinned'?
let isSaved = message.savedAt != 0

Check warning on line 142 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L142

Did you really mean 'isSaved'?

// A pin applied by an admin from the dashboard rather than a user
let isSystemPin = message.pinnedBy == "app_system"

Check warning on line 145 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L145

Did you really mean 'app_system'?
```
</Tab>
</Tabs>

---

## Fetch Pinned Messages

Pinned messages are fetched with `MessagesRequest` filtered by `pinned`, scoped to a conversation with `uid` or `guid`.

<Tabs>
<Tab title="Group">
```swift
let request = MessagesRequest.MessageRequestBuilder()
.set(guid: "cometchat-guid-1")
.set(pinned: true)
.set(limit: 100)
.build()

request.fetchPrevious { messages in
print("Pinned: \(messages?.count ?? 0)")
} onError: { error in
print("Error: \(error?.errorDescription)")
}
```
</Tab>
<Tab title="One-to-one">
```swift
let request = MessagesRequest.MessageRequestBuilder()
.set(uid: "cometchat-uid-1")
.set(pinned: true)
.set(limit: 100)
.build()

request.fetchPrevious { messages in
print("Pinned: \(messages?.count ?? 0)")
} onError: { error in

Check warning on line 182 in sdk/ios/pin-save-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/pin-save-message.mdx#L182

Did you really mean 'onError'?
print("Error: \(error?.errorDescription)")
}
```
</Tab>
</Tabs>

---

## Fetch Saved Messages

Saved messages are a per-user collection spanning every conversation, so the request takes **no** `uid` or `guid`.

<Tabs>
<Tab title="Swift">
```swift
let request = MessagesRequest.MessageRequestBuilder()
.set(saved: true)
.set(limit: 100)
.build()

request.fetchPrevious { messages in
// Each message carries receiverUid / receiverType identifying its source conversation
print("Saved: \(messages?.count ?? 0)")
} onError: { error in
print("Error: \(error?.errorDescription)")
}
```
</Tab>
</Tabs>

<Note>
Both limits are capped at 100 server-side, so a single page fetches the whole list.
</Note>

---

## Real-time Events

Implement `CometChatMessageDelegate` to receive pin and save updates. All four callbacks are optional and each carries the full updated message.

<Tabs>
<Tab title="Swift">
```swift
extension ViewController: CometChatMessageDelegate {

func onMessagePinned(message: BaseMessage) {
// Broadcast to everyone in the conversation
print("Pinned by \(message.pinnedBy)")
}

func onMessageUnpinned(message: BaseMessage) {
print("Unpinned: \(message.id)")
}

func onMessageSaved(message: BaseMessage) {
// Private — only reaches the saving user's other devices
print("Saved: \(message.id)")
}

func onMessageUnsaved(message: BaseMessage) {
print("Unsaved: \(message.id)")
}
}
```
</Tab>
</Tabs>

Register the delegate as you would for any message event — see [Real-time Delegates and Listeners](/sdk/ios/all-real-time-delegates-listeners).

Pin events are broadcast to every participant. Save events are private and reach only the saving user's other devices.

---

## Feature Availability

Both features are gated per app and can be checked before showing any UI:

<Tabs>
<Tab title="Swift">
```swift
if CometChat.isPinMessageEnabled() {
// Show pin options
}

if CometChat.isSaveMessageEnabled() {
// Show save options
}
```
</Tab>
</Tabs>

---

## Error Handling

| Error code | Meaning |
|------------|---------|
| `ERR_PINNED_MESSAGES_LIMIT_EXCEEDED` | The conversation already has the maximum pinned messages. |
| `ERR_SAVED_MESSAGES_LIMIT_EXCEEDED` | The user already has the maximum saved messages. |
| `ERR_PERMISSION_DENIED` | The user's scope does not allow pinning here. |
| `ERR_MESSAGE_NO_ACCESS` | The user cannot access this message. |
| `ERR_MESSAGE_ACTION_NOT_ALLOWED` | The action is not allowed on this message. |
| `ERR_FEATURE_NOT_ACCESSIBLE` | The feature is not enabled for this app. |

For the two limit errors, read the actual cap from the exception's `errorParams` rather than hard-coding a number — the limit is server-owned and may change.

---

## Edge Cases

| Scenario | Behavior |
|----------|----------|
| A pinned message is deleted | Automatically unpinned; no placeholder is left behind. |
| A pinned message is edited | Keeps its pin. |
| A saved message becomes inaccessible | Dropped from subsequent saved fetches. |
| A thread reply | Can be pinned and saved. Pinned lists return the parent message for context. |
| Someone else unpins your pin | Allowed — any user with permission can unpin. |

---

## Related

- [Pinned Messages UI Component](/ui-kit/ios/pinned-messages)
- [Saved Messages UI Component](/ui-kit/ios/saved-messages)
- [Additional Message Filtering](/sdk/ios/additional-message-filtering)
- [Real-time Delegates and Listeners](/sdk/ios/all-real-time-delegates-listeners)
6 changes: 5 additions & 1 deletion sdk/ios/send-message.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
let receiverID = "cometchat-uid-2"
let text = "Hello"

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

Check warning on line 40 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L40

Did you really mean 'textMessage'?

Check warning on line 40 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L40

Did you really mean 'receiverType'?

CometChat.sendTextMessage(message: textMessage, onSuccess: { (message) in

Check warning on line 42 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L42

Did you really mean 'textMessage'?

Check warning on line 42 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L42

Did you really mean 'onSuccess'?
print("TextMessage sent successfully. " + message.stringValue())
}) { (error) in
print("TextMessage sending failed with error: " + error!.errorDescription);
Expand All @@ -65,9 +65,9 @@
let receiverID = "cometchat-guid-102"
let text = "Hello"

let textMessage = TextMessage(receiverUid: receiverID, text: text, receiverType: .group)

Check warning on line 68 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L68

Did you really mean 'textMessage'?

Check warning on line 68 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L68

Did you really mean 'receiverType'?

CometChat.sendTextMessage(message: textMessage, onSuccess: { (message) in

Check warning on line 70 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L70

Did you really mean 'textMessage'?

Check warning on line 70 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L70

Did you really mean 'onSuccess'?
print("TextMessage sent successfully. " + message.stringValue())
}) { (error) in
print("TextMessage sending failed with error: " + error!.errorDescription);
Expand Down Expand Up @@ -113,8 +113,8 @@
</Tab>
<Tab title="Objective-C">
```objc
NSDictionary * metadata = @{@"latitude":@"50.6192171633316",@"longitude":@"-72.68182268750002"};

Check warning on line 116 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L116

Did you really mean 'NSDictionary'?
[textMessage setMetaData:metadata];

Check warning on line 117 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L117

Did you really mean 'textMessage'?
```
</Tab>
</Tabs>
Expand All @@ -122,10 +122,14 @@
### Add Tags

```swift
let tags = ["pinned"]
let tags = ["important"]
textMessage.tags = tags
```

<Note>
Tags are arbitrary labels of your own. To pin or save a message, use the dedicated APIs instead — see [Pin & Save Messages](/sdk/ios/pin-save-message).
</Note>

### Quote a Message

```swift
Expand All @@ -146,12 +150,12 @@
<Tabs>
<Tab title="Swift">
```swift
let receiverid = "cometchat-uid-2"

Check warning on line 153 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L153

Did you really mean 'receiverid'?
let mediaUrl = "file:///Library/Developer/CoreSimulator/.../image.jpg"

Check warning on line 154 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L154

Did you really mean 'mediaUrl'?

let mediaMessage = MediaMessage(receiverUid: receiverid, fileurl: mediaUrl, messageType: .image, receiverType: .user)

Check warning on line 156 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L156

Did you really mean 'mediaMessage'?

Check warning on line 156 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L156

Did you really mean 'receiverid'?

Check warning on line 156 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L156

Did you really mean 'fileurl'?

Check warning on line 156 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L156

Did you really mean 'mediaUrl'?

Check warning on line 156 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L156

Did you really mean 'messageType'?

Check warning on line 156 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L156

Did you really mean 'receiverType'?

CometChat.sendMediaMessage(message: mediaMessage, onSuccess: { (message) in

Check warning on line 158 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L158

Did you really mean 'mediaMessage'?

Check warning on line 158 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L158

Did you really mean 'onSuccess'?
print("MediaMessage sent successfully. " + message.stringValue())
}) { (error) in
print("MediaMessage sending failed with error: " + error.errorDescription);
Expand Down Expand Up @@ -293,12 +297,12 @@
<Tabs>
<Tab title="Swift (User)">
```swift
let receiverid = "cometchat-uid-2"

Check warning on line 300 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L300

Did you really mean 'receiverid'?
let customData: [String: Any] = ["customKey": "customData"]

Check warning on line 301 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L301

Did you really mean 'customData'?

Check warning on line 301 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L301

Did you really mean 'customKey'?

Check warning on line 301 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L301

Did you really mean 'customData'?

let customMessage = CustomMessage(receiverUid: receiverid, receiverType: .user, customData: customData, type: "Custom Type")

Check warning on line 303 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L303

Did you really mean 'customMessage'?

Check warning on line 303 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L303

Did you really mean 'receiverid'?

Check warning on line 303 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L303

Did you really mean 'receiverType'?

Check warning on line 303 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L303

Did you really mean 'customData'?

CometChat.sendCustomMessage(message: customMessage, onSuccess: { (message) in

Check warning on line 305 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L305

Did you really mean 'customMessage'?

Check warning on line 305 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L305

Did you really mean 'onSuccess'?
print("CustomMessage sent successfully. " + message.stringValue())
}) { (error) in
print("CustomMessage sending failed with error: " + error!.errorDescription);
Expand Down Expand Up @@ -375,7 +379,7 @@
```swift
let card = cardMessage.getCard() // raw card schema/payload
let text = cardMessage.getText() // optional text shown alongside the card
let fallbackText = cardMessage.getFallbackText() // shown when the card cannot be rendered

Check warning on line 382 in sdk/ios/send-message.mdx

View check run for this annotation

Mintlify / Mintlify Validation (cometchat-22654f5b) - vale-spellcheck

sdk/ios/send-message.mdx#L382

Did you really mean 'fallbackText'?
let tags = cardMessage.getTags() // tags associated with the message
```
</Tab>
Expand Down
Loading