Retrieve Historical Messages
When retrieving historical messages, you can choose to fetch them only from local storage, only from remote servers, or simultaneously from both local and remote sources.
Enable Service
The Cloud Storage for One-to-One and Group Messages service is enabled by default. You can retrieve historical one-to-one and group chat messages from remote servers directly. For production environment App Keys, this service is available for Chat Starter Plan and Chat Pro Plan. Specific features and pricing are subject to the RC Official Pricing Page.
Please distinguish between historical message records and offline messages?. RC provides default offline message caching for up to 7 days (configurable) for one-to-one chats, group chats, and system messages. The SDK automatically retrieves messages received during offline periods when the client comes online, with no need for app-layer API calls. See Manage Offline Message Storage Configuration for details.
Retrieve Messages from Local Database
You can use the getHistoryMessages method to paginate through historical messages stored in the local database for a specified conversation, obtaining an asynchronously returned list of message objects. Messages in the list are ordered from newest to oldest by send time.
The IMLib SDK has supported asynchronous message list retrieval since version 5.3.0. If your version is below 5.3.0 or you need synchronous message list retrieval, you can find and use the getHistoryMessages method with the same name in the IMLib SDK.
Retrieve Messages Before a Specified messageId in a Conversation
Method Signature
targetId:(NSString *)targetId
oldestMessageId:(long)oldestMessageId
count:(int)count
completion:(nullable void(^)(NSArray<RCMessage *> *_Nullable messages))completion;
Parameter Description
The count parameter specifies how many messages should be included in the returned list. The oldestMessageId parameter controls pagination boundaries. Each call to getHistoryMessages uses the message pointed to by oldestMessageId as a boundary, continuing to return the specified number of messages on the next page. To retrieve the latest count messages in a conversation, set oldestMessageId to -1.
We recommend using the messageId of the earliest message in the returned results as the oldestMessageId for the next call, enabling you to traverse the entire conversation's message history.
| Parameter | Type | Description |
|---|---|---|
| conversationType | [RCConversationType] | Conversation type |
| targetId | NSString | Conversation ID |
| oldestMessageId | long | Pagination boundary - retrieves count messages with smaller send times than this messageId. Set to -1 or 0 to get the latest count messages. |
| count | int | Number of messages to retrieve, ordered from newest to oldest by send time |
| completion | Block | Asynchronous callback returning an array of retrieved message objects RCMessage |
Example Code
[[RCCoreClient sharedCoreClient] getHistoryMessages:ConversationType_PRIVATE
targetId:@"targetId"
oldestMessageId:-1
count:10
completion:^(NSArray<RCMessage *> * _Nullable messages) {
}];
Retrieve Messages Around a Specified Timestamp
Asynchronously retrieves the specified number of latest message objects before and after a given timestamp in a conversation, returning a list of RCMessage objects.
Method Signature
- (void)getHistoryMessages:(RCConversationType)conversationType
targetId:(NSString *)targetId
sentTime:(long long)sentTime
beforeCount:(int)beforeCount
afterCount:(int)afterCount
completion:(nullable void(^)(NSArray<RCMessage *> * _Nullable messages))completion;
Parameter Description
| Parameter | Type | Description |
|---|---|---|
| conversationType | [RCConversationType] | Conversation type |
| targetId | NSString | Conversation ID |
| sentTime | long long | Boundary timestamp - retrieves messages before or after this time. |
| beforeCount | int | Number of messages to retrieve with send times earlier than the specified timestamp. |
| afterCount | int | Number of messages to retrieve with send times later than the specified timestamp. |
| completion | Block | Callback for retrieved messages. |
Example Code
[[RCCoreClient sharedCoreClient] getHistoryMessages:ConversationType_PRIVATE
targetId:@"targetId"
sentTime:0
beforeCount:10
afterCount:10 completion:^(NSArray<RCMessage *> * _Nullable messages) {
}];
Retrieve Messages of Specified Types in a Conversation
Method Signature
- (void)getHistoryMessages:(RCConversationType)conversationType
targetId:(NSString *)targetId
objectName:(nullable NSString *)objectName
oldestMessageId:(long)oldestMessageId
count:(int)count
completion:(nullable void(^)(NSArray<RCMessage *> *_Nullable messages))completion;
Parameter Description
| Parameter | Type | Description |
|---|---|---|
| conversationType | [RCConversationType] | Conversation type. |
| targetId | NSString | Conversation ID. |
| objectName | NSString | Message type identifier. Built-in message type identifiers can be found in [Message Type Overview]. |
| oldestMessageId | long | Pagination boundary - retrieves count messages with smaller send times than this messageId. Set to -1 or 0 to get the latest count messages. |
| count | int | Number of messages to retrieve, ordered from newest to oldest by send time |
| completion | Block | Asynchronous callback returning an array of retrieved message objects RCMessage |
Example Code
[[RCCoreClient sharedCoreClient] getHistoryMessages:ConversationType_PRIVATE
targetId:@"targetId"
objectName:@"RC:TxtMsg"
oldestMessageId:-1
count:10
completion:^(NSArray<RCMessage *> * _Nullable messages) {
}];
To retrieve historical messages before or after a specified message, you can use the following method with the isForward parameter:
Method Prototype
- (void)getHistoryMessages:(RCConversationType)conversationType
targetId:(NSString *)targetId
objectName:(nullable NSString *)objectName
baseMessageId:(long)baseMessageId
isForward:(BOOL)isForward
count:(int)count
completion:(nullable void(^)(NSArray<RCMessage *> *_Nullable messages))completion;
#### Parameter Description
| Parameter | Type | Description |
|:-----------------|:---------------------|:------------------------------------------------------------------------------------------------------------|
| conversationType | [RCConversationType] | Conversation type. |
| targetId | NSString | Conversation ID. |
| objectName | NSString | Message type identifier. For built-in message type identifiers, refer to [Message Type Overview]. |
| baseMessageId | long | Controls pagination boundary. Retrieves `count` messages with smaller timestamps than this messageId. Set to -1 or 0 to get the latest `count` messages. |
| isForward | BOOL | Query direction: true for forward, false for backward. |
|---|---|---|
| count | int | Number of messages to retrieve, sorted by send time from newest to oldest. |
| completion | Block | Asynchronous callback that returns an array of retrieved message entities `RCMessage`. |
#### Example Code
```objectivec
[[RCCoreClient sharedCoreClient] getHistoryMessages:ConversationType_PRIVATE
targetId:@"targetId"
objectName:@"RC:TxtMsg"
baseMessageId:-1
isForward:true
count:10
completion:^(NSArray<RCMessage *> * _Nullable messages) {
}];
### Retrieving Messages by messageUId
:::tip
- Starting from SDK version 5.2.5.1, batch message retrieval by messageUId is supported. This interface is only available in the `RCChannelClient` class. Supported conversation types include one-to-one chat, group chat, chatroom, and ultra group.
- For SDK versions below 5.2.5.1, use the `getMessageByUId` method in the `RCCoreClient` class, which supports only one messageUId per call.
:::
The messageUId is a globally unique ID generated by the RC server for messages. Once a message is stored in the local database, you can retrieve it using its messageUId.
For example, if your users want to bookmark certain messages from chat history, the app can first record the messageUIds of those messages. When needed, call `getBatchLocalMessages` with the bookmarked messageUIds to retrieve the messages from the local database.
#### Interface Prototype
```objectivec
- (void)getBatchLocalMessages:(RCConversationType)conversationType
targetId:(NSString *)targetId
channelId:(nullable NSString *)channelId
messageUIDs:(NSArray<NSString *> *)messageUIDs
success:(nullable void (^)(NSArray<RCMessage *> *messages, NSArray<NSString *> *mismatch))successBlock
error:(nullable void (^)(RCErrorCode status))errorBlock;
#### Parameter Description
| Parameter | Type | Description |
|:-----------------|:---------------------|:------------------------------------------------------------------------------------|
| conversationType | [RCConversationType] | Conversation type, supporting one-to-one chat, group chat, chatroom, and ultra group. |
| targetId | NSString | Conversation ID. |
| channelId | NSString | Channel ID for ultra groups. Pass `null` for non-ultra group conversations. |
| messageUIDs | NSArray | Array of messageUIds (globally unique IDs generated by RC server). Must be valid messageUIds, with a maximum of 20. |
| successBlock | Block | Success callback. Returns an array of message objects and an array of failed messageUIds. |
| errorBlock | Block | Failure callback. |
#### Example Code
```objectivec
[[RCChannelClient sharedChannelManager] getBatchLocalMessages:conversationType_PRIVATE
targetId: @"targetId"
channelId: nil
messageUIDs:@[@"C3GC-8VAA-LJQ4-TPPM", @"B5GC-3VAA-LJQ4-TXXA"]
success:^(NSArray<RCMessage *> *messages, NSArray<NSString *> *mismatch) {
}
error:^(RCErrorCode status) {
}];
:::tip
- The target messages must exist in the local database.
- Only messages from a single conversation (`targetId`) or ultra group channel (`channelId`) can be retrieved per call.
- Ultra group conversations only synchronize the last message by default. If you directly call this method (e.g., passing messageUIds obtained via RC server callbacks for **Post-messaging Callback**), the IMLib SDK may fail to locate the corresponding messages locally. It is recommended to first call `getBatchRemoteUltraGroupMessages` to retrieve messages from the server.
- Chatroom messages are automatically cleared from local storage when users leave the chatroom. If this interface is called after leaving, local messages cannot be retrieved.
:::
## Retrieving Remote History Messages \{#getmsgremote}
You can use the `getRemoteHistoryMessages` method to directly query historical messages stored in **Cloud Storage for One-to-One and Group Messages** for a specified conversation.
:::tip
- Whether users can retrieve group chat history messages sent before they joined depends on the settings of the corresponding App Key in the RC Console. You can enable **Retrieve group history when not in group** in the [RC Console](https://console.rongcloud.io/agile/im/service/config) under **Chat** > **Chat settings** > **One-to-One and Group Chats** > **Retrieve group history when not in group**. When enabled, new group members can access all group messages sent before they joined. If disabled, they can only see messages sent after joining.
- By default, users cannot retrieve group history messages when not in the group. To allow users to retrieve group history messages even when not in the group, go to the [RC Console](https://console.rongcloud.io/agile/im/service/config), under **Chat** > **Chat settings** > **One-to-One and Group Chats** > **Retrieve group history when not in group**, and enable this option.
:::
:::
### Retrieving Remote History Messages for a Conversation
The IMLib SDK can directly query and retrieve remote history messages from **Cloud Storage for One-to-One and Group Messages** that meet specified conditions. The query results are compared with the local database to exclude duplicate messages before returning a list of message objects. The returned message list is sorted by send time from newest to oldest.
:::tip
- Since this interface by default returns messages after deduplication against local messages, it is recommended to first use `getHistoryMessages` to retrieve all messages in the local database, then use the `sentTime` of the last local message as `recordTime` to fetch remote history messages. This method cannot retrieve missing messages. To obtain missing messages, use the `getMessages` interface to fetch both local and remote history messages.
:::
####
```objectivec
- (void)getRemoteHistoryMessages:(RCConversationType)conversationType
targetId:(NSString *)targetId
recordTime:(long long)recordTime
count:(int)count
success:(nullable void (^)(NSArray<RCMessage *> *messages, BOOL isRemaining))successBlock
error:(nullable void (^)(RCErrorCode status))errorBlock;
#### Parameter Description
| Parameter | Type | Description |
|:-----------------|:---------------------|:-------------------------------------------------------------------------------------------------------|
| conversationType | [RCConversationType] | Conversation type |
| targetId | NSString | Conversation ID |
| recordTime | long long | Timestamp used to control pagination boundaries, retrieving history messages sent before `recordTime`. Passing `0` fetches the latest `count` messages. Default is `0`. Each call to `getRemoteHistoryMessages` uses `recordTime` as a boundary to continue returning the specified number of messages on the next page. It is recommended to use the `sentTime` of the earliest message in the returned results as the `recordTime` value for the next call to traverse the entire conversation history. |
| count | int | Number of messages to retrieve. For SDK versions \< 5.4.1, the range is [2-20]; for SDK versions ≧ 5.4.1, the range is [2-100]. |
| successBlock | Block | Success callback |
| errorBlock | Block | Failure callback |
- `success` description:
| Callback Parameter | Callback Type | Description |
|:-------------------|:-------------|:---------------------------|
| messages | NSArray | Retrieved history message array |
| isRemaining | BOOL | Whether more messages remain |
- `error` description:
| Callback Parameter | Callback Type | Description |
|:-------------------|:------------------------------------------------------------------------------------------------------------------------------------|:-----------------------|
| status | [RCErrorCode](https://doc.rongcloud.cn/apidoc/imlibcore-ios/latest/zh_CN/documentation/rongimlibcore/rcerrorcode?language=objc) | Error code for failure |
#### Example Code
```objectivec
[[RCIMClient sharedRCIMClient] getRemoteHistoryMessages:ConversationType_PRIVATE
targetId:@"targetId"
recordTime:0
count:count
success:^(NSArray *messages, BOOL isRemaining) {
} error:^(RCErrorCode status) {
}];
### Custom Retrieval of Remote History Messages for a Conversation
You can customize the behavior of the `getRemoteHistoryMessages` method using `RCRemoteHistoryMsgOption` to retrieve remote history messages. The IMLib SDK will directly query **Cloud Storage for One-to-One and Group Messages** for history messages that meet the specified conditions.
:::tip
- Since the `getRemoteHistoryMessages` method by default returns messages after deduplication against local messages, it is recommended to first use `getHistoryMessages` to retrieve all messages in the local database, then use the `sentTime` of the last local message as `recordTime` to fetch remote history messages. This method cannot retrieve missing messages. To obtain missing messages, use the `getMessages` interface to fetch both local and remote history messages.
:::
#### Interface Prototype
```objectivec
- (void)getRemoteHistoryMessages:(RCConversationType)conversationType
targetId:(NSString *)targetId
option:(RCRemoteHistoryMsgOption *)option
success:(nullable void (^)(NSArray<RCMessage *> *messages, BOOL isRemaining))successBlock
error:(nullable void (^)(RCErrorCode status))errorBlock;
#### Parameter Description
`RCRemoteHistoryMsgOption` contains multiple configuration items, where the `count` and `recordTime` parameters specify the number of history messages to retrieve and the pagination timestamp, respectively. The `order` parameter controls the time direction for retrieving history messages, allowing selection of messages either earlier or later than the given `recordTime`. The `includeLocalExistMessage` parameter determines whether the returned message list should include messages already present in the local database.
By default, `RCRemoteHistoryMsgOption` queries messages in a conversation in descending order of send time and compares the results with the local database to exclude duplicate messages before returning the message object list. When `includeLocalExistMessage` is set to `NO`, it is recommended that the app layer first uses `getHistoryMessages` to retrieve all messages in the local database before fetching remote history messages; otherwise, locally existing messages might not be retrieved.
To query messages in ascending order of send time, it is recommended to use the `sentTime` of the newest message in the returned results as the `recordTime` value for the next call to traverse the entire conversation history. Ascending order queries are typically useful for scenarios where you need to retrieve newer history messages after jumping to a specific message position in the conversation UI.
| Parameter | Type | Description |
|:-----------------|:-------------------------|:-------------------------------------------|
| conversationType | [RCConversationType] | Conversation type |
| targetId | NSString | Conversation ID |
| option | RCRemoteHistoryMsgOption | Configurable parameters including count, order, etc. |
| successBlock | Block | Success callback |
| errorBlock | Block | Failure callback |
- **`RCRemoteHistoryMsgOption` Description**:
| Parameter | Description |
|:-------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| recordTime | Timestamp used to control the boundary for paginated message queries. Default value is `0`. |
| count | Number of messages to retrieve. For SDK versions < 5.4.1, the range is [2-20]; for SDK versions ≥ 5.4.1, the range is [2-100]. Default value is `0`, indicating no retrieval. |
| order | Retrieval order. `RCRemoteHistoryOrderDesc`: Descending order - retrieves messages with send times earlier than `recordTime` in chronological descending order, returning messages sorted from newest to oldest. `RCRemoteHistoryOrderAsc`: Ascending order - retrieves messages with send times later than `recordTime` in chronological ascending order, returning messages sorted from oldest to newest. Default value is `RCRemoteHistoryOrderDesc`. |
| includeLocalExistMessage | Whether to include existing messages from the local database. `YES`: Includes messages - query results are not deduplicated against the local database, directly returning historical messages from the server. `NO`: Excludes messages - query results are first deduplicated against the local database, returning only messages that don't exist locally. Default value is `NO`. |
- `success` description:
| Callback Parameter | Callback Type | Description |
|:------------|:---------|:-------------------|
| messages | NSArray | Retrieved historical message array |
| isRemaining | BOOL | Whether there are remaining messages |
- `error` description:
| Callback Parameter | Callback Type | Description |
|:---------|:--------------------------------------------------------------------------------------------------------------------------------|:---------------|
| status | [RCErrorCode](https://doc.rongcloud.cn/apidoc/imlibcore-ios/latest/zh_CN/documentation/rongimlibcore/rcerrorcode?language=objc) | Error code for failed retrieval |
#### Sample Code
```objectivec
RCRemoteHistoryMsgOption *option = [RCRemoteHistoryMsgOption new];
option.recordTime = recordTime;
option.count = 10;
option.order = RCRemoteHistoryOrderDesc;
option.includeLocalExistMessage = NO;
[[RCIMClient sharedRCIMClient] getRemoteHistoryMessages:ConversationType_PRIVATE targetId:@"targetId" option:option success:^(NSArray *messages, BOOL isRemaining) {
} error:^(RCErrorCode status) {
}];
## Retrieving Local and Remote Historical Messages\{#getmsgs}
:::tip
- Whether users can retrieve group chat history messages sent before they joined depends on the App's settings in the Console. You can enable **Retrieve group history when not in group** in the [RC Console](https://console.rongcloud.io/agile/im/service/config) under **Chat** > **Chat settings** > **One-to-One and Group Chats** > **Retrieve group history when not in group**. When enabled, newly joined group members can retrieve all group chat messages sent before they joined. If disabled, new members can only see messages sent after they joined.
- By default, users cannot retrieve group history messages when not in the group. If you want users to be able to retrieve group history messages even when not in the specified group, you can enable this feature in the [RC Console](https://console.rongcloud.io/agile/im/service/config) under **Chat** > **Chat settings** > **One-to-One and Group Chats** > **Retrieve group history when not in group**.
- The `getMessages` method can retrieve discontinuous messages.
:::
The difference between `getMessages` and `getRemoteHistoryMessages` is that `getMessages` first queries messages stored in the local database for the specified conversation. When local messages cannot satisfy the query conditions, it then queries historical messages in **Cloud Storage for One-to-One and Group Messages**, returning a continuous and adjacent list of message objects.
You can customize the behavior of the `getMessages` method for retrieving remote historical messages through the `RCHistoryMessageOption` configuration:
#### Interface Prototype
```objectivec
- (void)getMessages:(RCConversationType)conversationType
targetId:(NSString *)targetId
option:(RCHistoryMessageOption *)option
complete:(nullable void (^)(NSArray <RCMessage *> * _Nullable messages,long long timestamp, BOOL isRemaining, RCErrorCode code))complete
error:(nullable void (^)(RCErrorCode status))errorBlock;
#### Parameter Description
`RCHistoryMessageOption` contains multiple configuration items. The `count` parameter indicates how many messages should be included in the returned list. The `recordTime` parameter controls the boundary for pagination. Each time the `getMessages` method is called, the SDK uses `recordTime` as the boundary to continue returning the specified number of messages on the next page. To retrieve the latest `count` messages in the conversation, set `recordTime` to 0. The `Order` parameter controls the chronological direction for retrieving historical messages, allowing selection of messages either earlier or later than the given `recordTime`.
`RCHistoryMessageOption` defaults to descending order when querying conversation messages. It is recommended to obtain the `sentTime` of the earliest message in the returned results and use it as the `recordTime` value in the next call to traverse the entire conversation history. Ascending order queries are typically used when jumping to a specific message position in the conversation UI and needing to query newer historical messages.
| Parameter | Type | Description |
|:-----------------|:-----------------------|:-----------------------------------|
| conversationType | [RCConversationType] | Conversation type |
| targetId | NSString | Conversation ID |
| option | RCHistoryMessageOption | Configurable parameters including retrieval count and order |
| complete | Block | Message retrieval callback |
- **`RCHistoryMessageOption` Description**:
| Parameter | Description |
|:-----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| recordTime | Timestamp used to control the boundary for paginated message queries. Default value is `0`. |
| count | Number of messages to retrieve. For SDK versions \< 5.4.1, the range is [2-20]; for SDK versions ≧ 5.4.1, the range is [2-100]; default value is `0`, indicating no retrieval. |
| order | Retrieval order. `RCHistoryMessageOrderDesc`: Descending order - retrieves messages with send times earlier than `recordTime` in chronological descending order, returning messages from newest to oldest. `RCHistoryMessageOrderAsc`: Ascending order - retrieves messages with send times later than `recordTime` in chronological ascending order, returning messages from oldest to newest. Default is descending order. |
#### Sample Code
```objectivec
RCHistoryMessageOption *option = [[RCHistoryMessageOption alloc] init];
option.order = RCHistoryMessageOrderDesc;
option.count = 20;
option.recordTime = message.sentTime; // Pass 0 to retrieve the latest 20 messages.
[[RCCoreClient sharedCoreClient] getMessages:ConversationType_PRIVATE targetId:@"conversation id" option:option complete:^(NSArray *messages, RCErrorCode code) {
if (code == 0) {
// Success
} else {
// Failure
}
}];
<!--links-->
[Message Type Overview]: /platform-chat-api/message-about/about-message-types
[Feature Configuration]: https://console.rongcloud.io/agile/im/service/config
[RCConversationType]: https://doc.rongcloud.cn/apidoc/imlibcore-ios/latest/zh_CN/documentation/rongimlibcore/rcconversationtype?language=objc