---
title: 获取历史消息
sidebar_position: 30
---
# 获取历史消息
获取历史消息可以仅从本地数据中获取,仅从远端获取,和同时从本地与远端获取。
## 开通服务
从远端获取单群聊历史消息是指从融云服务端获取历史消息,该功能要求 App Key 已启用融云提供的**单群聊消息云端存储**服务。您可以在控制台 [IM 服务管理](https://console.rongcloud.cn/agile/formwork/advance/index)页面为当前使用的 App Key 开启服务。如果使用生产环境的 App Key,请注意仅 **IM 旗舰版**或 **IM 尊享版**可开通该服务。具体功能与费用以[融云官方价格说明](https://www.rongcloud.cn/pricing)页面及[计费说明](https://help.rongcloud.cn/t/topic/123)文档为准。
**提示**:请注意区分历史消息记录与离线消息?。融云针对单聊、群聊、系统消息默认提供最多 7 天(可调整)的离线消息缓存服务。客户端上线时 SDK 会自动收取离线期间的消息,无需 App 层调用 API。详见[管理离线消息存储配置](./manage-offline-message-duration.md)。
## 从本地数据库中获取消息 {#getmsglocal}
使用 `getHistoryMessages` 方法可分页查询指定会话存储在本地数据库中的历史消息,并返回消息对象列表。列表中的消息按发送时间从新到旧排列。
### 获取会话中所有类型的消息
返回消息实体 RCMessage 对象列表。
```objectivec
NSArray *history = [[RCIMClient sharedRCIMClient]
getHistoryMessages:ConversationType_PRIVATE
targetId:@"targetId"
oldestMessageId:lastMessageID
count:count];
```
`count` 参数表示返回列表中应包含多少消息。`oldestMessageId` 参数用于控制分页的边界。每次调用 `getHistoryMessages` 方法时,SDK 会以 `oldestMessageId` 参数指向的消息为界,继续在下一页返回指定数量的消息。如果需要获取会话中最新的 `count` 条消息,可以将 `oldestMessageId` 设置为 -1。
建议获取返回结果中最早一条消息的 ID,并在下一次调用时作为 `oldestMessageId` 传入,以便遍历整个会话的消息历史记录。
| 参数 | 类型 | 说明 |
|:-----------------|:---------------------|:-----------------------------------------------------------------------------------------------------|
| conversationType | [RCConversationType] | 会话类型 |
| targetId | NSString | 会话 Id |
| oldestMessageId | long | 以此 messageId 为界,获取发送时间更小的 count 条消息。ID 不存在时,设置为 -1,表示获取最新的 count 条消息。 |
| count | int | 需要获取的消息数量,按照消息发送时间从新到旧排列 |
### 获取会话中指定类型的消息 {#getMsgLocal_obj}
返回消息实体 RCMessage 对象列表。
```objectivec
NSArray *history = [[RCIMClient sharedRCIMClient] getHistoryMessages:ConversationType_PRIVATE targetId:@"targetId" objectName:@"RC:TxtMsg" oldestMessageId:lastMessageID count:count];
```
`count` 参数表示返回列表中应包含多少消息。`oldestMessageId` 参数用于控制分页的边界。每次调用 `getHistoryMessages` 方法时,SDK 会以 `oldestMessageId` 参数指向的消息为界,继续在下一页返回指定数量的消息。如果需要获取会话中最新的 `count` 条消息,可以将 `oldestMessageId` 设置为 -1。
建议获取返回结果中最早一条消息的 ID,并在下一次调用时作为 `oldestMessageId` 传入,以便遍历整个会话的消息历史记录。
| 参数 | 类型 | 说明 |
|:-----------------|:---------------------|:-----------------------------------------------------------------------------------------------------|
| conversationType | [RCConversationType] | 会话类型。 |
| targetId | NSString | 会话 ID。 |
| objectName | NSString | 消息类型标识。内置消息类型的标识可参见[消息类型概述]。 |
| oldestMessageId | long | 以此 messageId 为界,获取发送时间更小的 count 条消息。ID 不存在时,设置为 -1,表示获取最新的 count 条消息。 |
| count | int | 需要获取的消息数量,按照消息发送时间从新到旧排列 |
### 通过消息 UID 获取消息
:::tip
- SDK 从 5.2.5.1 版本开始支持通过 UID 批量获取消息的接口。仅在 `RCChannelClient` 类中提供。支持的会话类型包括单聊、群聊、聊天室、超级群。
- 如果 SDK 版本低于 5.2.5.1,可以使用 `RCCoreClient` 类中的 `getMessageByUId` 方法,该方法一次仅支持传入一个 UID。
:::
消息的 UID 是由融云服务端生成的全局唯一 ID。消息存入本地数据库后,App 可能需要再次提取特定消息。例如,您的用户希望收藏聊天记录中的部分消息,App 可以先记录消息的 UID,在需要展示时调用 `getBatchLocalMessages`,传入收藏消息的 UID,从本地数据库中提取消息。
```objectivec
[[RCChannelClient sharedChannelManager] getBatchLocalMessages:conversationType_PRIVATE
targetId: @"targetId"
channelId: nil
messageUIDs:@[@"C3GC-8VAA-LJQ4-TPPM", @"B5GC-3VAA-LJQ4-TXXA"]]
success:^(NSArray *messages, NSArray *mismatch)) {}
error:^(RCErrorCode status) {};
```
只要持有消息 UID(`messageUIDs`),并且本地数据库中已存有消息,即可以使用该方法从本地数据库提取消息。单次仅可从一个会话(`targetId`)或超级群频道(`channelId`)中提取消息。
| 参数 | 类型 | 说明 |
|:-----------------|:---------------------|:----------------------------------------------------------------------------|
| conversationType | [RCConversationType] | 会话类型,支持单聊、群聊、聊天室、超级群。 |
| targetId | NSString | 会话 ID |
| channelId | NSString | 超级群的频道 ID。非超级群会话类型时,传入 `null`。 |
| messageUIDs | NSArray | 消息的 UID,即由融云服务端生成的全局唯一 ID。必须传入有效的 UID,最多支持 20 条。 |
| successBlock | Block | 成功回调。返回结果中包含消息对象列表和提取失败的消息的 UID 列表。 |
| errorBlock | Block | 失败回调。 |
在会话类型为**超级群**或**聊天室**时,请注意以下情况:
- 超级群会话默认只同步会话最后一条消息。如果您直接调用该方法(例如您传入了通过融云服务端回调**全量消息路由**获取的 UID),可能 SDK 无法在本地找到对应消息。建议先调用 `getBatchRemoteUltraGroupMessages` 从服务端获取消息。
- 聊天室会话自动在用户退出清空本地消息。如果用户退出聊天室后再调用该接口,则无法取得本地消息。
## 获取远端历史消息 {#getmsgremote}
使用 `getRemoteHistoryMessages` 方法可直接查询指定会话存储在**单群聊消息云端存储**中的历史消息。
:::tip
用户是否可以获取在加入群组之前的群聊历史消息取决于 App 在控制台的设置。您可以在控制台的[免费基础功能]页面,启用**新用户获取加入群组前历史消息**。启用此选项后,新入群用户可以获取在他们加入群组之前发送的所有群聊消息。如不启用,新入群用户只能看到他们入群后的群聊消息。
:::
### 获取会话的远端历史消息
SDK 按照指定条件直接查询并获取**单群聊消息云端存储**中的满足查询条件的历史消息。查询结果与本地数据库对比,排除重复的消息后,返回消息对象列表。返回的消息列表中的消息按发送时间从新到旧排列。
因为默认该接口返回的消息会跟本地消息排重后返回,建议先使用 `getHistoryMessages`,在本地数据库消息全部获取完之后,再获取远端历史消息。否则可能会获取不到指定的部分或全部消息。
```objectivec
[[RCIMClient sharedRCIMClient] getRemoteHistoryMessages:ConversationType_PRIVATE targetId:@"targetId" recordTime:recordTime count:count success:^(NSArray *messages, BOOL isRemaining) {
} error:^(RCErrorCode status) {
}];
```
`count` 参数表示返回列表中应包含多少消息。`recordTime` 参数用于控制分页的边界。每次调用 `getRemoteHistoryMessages` 方法时,SDK 会以 `recordTime` 为界,继续在下一页返回指定数量的消息。如果需要获取会话中最新的 `count` 条消息,可以将 `recordTime` 设置为 0。
建议获取返回结果中最早一条消息的 `sentTime`,并在下一次调用时作为 `recordTime` 的值传入,以便遍历整个会话的消息历史记录。
| 参数 | 类型 | 说明 |
|:-----------------|:---------------------|:-----------------------------------------------------------------------------------------------|
| conversationType | [RCConversationType] | 会话类型 |
| targetId | NSString | 会话 ID |
| recordTime | long long | 时间戳,获取发送时间早于 `recordTime` 的历史消息。传 `0` 表示获取最新 `count` 条消息。默认值为 `0`。 |
| count | int | 要获取的消息数量。如果 SDK \< 5.4.1,范围为 [2-20];如果 SDK ≧ 5.4.1,范围为 [2-100]。 |
| successBlock | Block | 获取成功的回调 |
| errorBlock | Block | 获取失败的回调 |
- `success` 说明:
| 回调参数 | 回调类型 | 说明 |
|:------------|:---------|:-------------------|
| messages | NSArray | 获取到的历史消息数组 |
| isRemaining | BOOL | 是否还有剩余消息 |
- `error` 说明:
| 回调参数 | 回调类型 | 说明 |
|:---------|:--------------------------------------------------------------------------------------------------------------------------------|:---------------|
| status | [RCErrorCode](https://doc.rongcloud.cn/apidoc/imlibcore-ios/latest/zh_CN/documentation/rongimlibcore/rcerrorcode?language=objc) | 获取失败的错误码 |
### 自定义获取会话的远端历史消息
通过 `RCRemoteHistoryMsgOption` 可以自定义 `getRemoteHistoryMessages` 方法获取远端历史消息的行为。SDK 会按照指定条件直接查询**单群聊消息云端存储**中的满足查询条件的历史消息。
`RCRemoteHistoryMsgOption` 中包含多个配置项,其中 `count` 与 `recordTime` 参数分别时获取历史消息的数量与分页查询时间戳。`order` 参数用于控制获取历史消息的时间方向,可选择获取早于或者晚于给定的 `recordTime` 的消息。`includeLocalExistMessage` 参数控制返回消息列表中是否需要包含本地数据库已存在的消息。
```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) {
}];
```
`RCRemoteHistoryMsgOption` 默认按消息发送时间降序查询会话中的消息,且默认会并将查询结果与本地数据库对比,排除重复的消息后,再返回消息对象列表。在 `includeLocalExistMessage` 设置为 `NO` 的情况下,建议 App 层先使用 `getHistoryMessages`,在本地数据库消息全部获取完之后,再获取远端历史消息,否则可能会获取不到指定的部分或全部消息。
如需按消息发送时间升序查询会话中的消息,建议获取返回结果中最新一条消息的 `sentTime`,并在下一次调用时作为 `recordTime` 的值传入,以便遍历整个会话的消息历史记录。升序查询消息一般可用于跳转到会话页面指定消息位置后需要查询更新的历史消息的场景。
| 参数 | 类型 | 说明 |
|:-----------------|:-------------------------|:-----------------------------------|
| conversationType | [RCConversationType] | 会话类型 |
| targetId | NSString | 会话 ID |
| option | RCRemoteHistoryMsgOption | 可配置的参数,包括拉取数量、拉取顺序等 |
| successBlock | Block | 获取成功的回调 |
| errorBlock | Block | 获取失败的回调 |
- **`RCRemoteHistoryMsgOption` 说明**:
| 参数 | 说明 |
|:-------------------------|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| recordTime | 时间戳,用于控制分页查询消息的边界。默认值为 `0`。 |
| count | 要获取的消息数量。如果 SDK \< 5.4.1,范围为 [2-20];如果 SDK ≧ 5.4.1,范围为 [2-100];默认值为 `0`,表示不获取。 |
| order | 拉取顺序。`RCRemoteHistoryOrderDesc`:降序,按消息发送时间递减的顺序,获取发送时间早于 `recordTime` 的消息,返回的列表中的消息按发送时间从新到旧排列。`RCRemoteHistoryOrderAsc`:升序,按消息发送时间递增的顺序,获取发送时间晚于 `recordTime` 的消息,返回的列表中的消息按发送时间从旧到新排列。默认值为 `1`。 |
| includeLocalExistMessage | 是否包含本地数据库中的已有消息。`YES`:包含,查询结果不与本地数据库排除重复,直接返回。`NO`:不包含,查询结果先与本地数据库排除重复,只返回本地数据库中不存在的消息。默认值为 `NO`。 |
- `success` 说明:
| 回调参数 | 回调类型 | 说明 |
|:------------|:---------|:-------------------|
| messages | NSArray | 获取到的历史消息数组 |
| isRemaining | BOOL | 是否还有剩余消息 |
- `error` 说明:
| 回调参数 | 回调类型 | 说明 |
|:---------|:--------------------------------------------------------------------------------------------------------------------------------|:---------------|
| status | [RCErrorCode](https://doc.rongcloud.cn/apidoc/imlibcore-ios/latest/zh_CN/documentation/rongimlibcore/rcerrorcode?language=objc) | 获取失败的错误码 |
## 获取本地与远端历史消息
:::tip
该接口在 `RCCoreClient` 类中提供。**注意**:用户是否可以获取在加入群组之前的群聊历史消息取决于 App 在控制台的设置。您可以在控制台的[免费基础功能]页面,启用**新用户获取加入群组前历史消息**。启用此选项后,新入群用户可以获取在他们加入群组之前发送的所有群聊消息。如不启用,新入群用户只能看到他们入群后的群聊消息。
:::
`getMessages` 方法与 `getRemoteHistoryMessages` 的区别是 `getMessages` 会先查询指定会话存储本地数据库的消息,当本地消息无法满足查询条件时,再查询在**单群聊消息云端存储**中的历史消息,以返回连续且相邻的消息对象列表。
通过 `getMessages` 的 `RCHistoryMessageOption` 配置,可以自定义 `getMessages` 方法获取远端历史消息的行为。
```objectivec
RCHistoryMessageOption *option = [[RCHistoryMessageOption alloc] init];
option.order = RCHistoryMessageOrderDesc;
option.count = 20;
option.recordTime = message.sentTime; // 如果获取最新的 20 条消息,可以传 0。
[[RCCoreClient sharedCoreClient] getMessages:ConversationType_PRIVATE targetId:@"会话 id" option:option complete:^(NSArray *messages, RCErrorCode code) {
if (code == 0) {
// 成功
} else {
// 失败
}
}];
```
`RCHistoryMessageOption` 中包含多个配置项,`count` 参数表示返回列表中应包含多少消息。`recordTime` 参数用于控制分页的边界。每次调用 `getMessages` 方法时,SDK 会以 `recordTime` 为界,继续在下一页返回指定数量的消息。如果需要获取会话中最新的 `count` 条消息,可以将 `recordTime` 设置为 0。`Order` 参数用于控制获取历史消息的时间方向,可选择获取早于或者晚于给定的 `recordTime` 的消息。
`RCHistoryMessageOption` 默认降序查询会话中的消息,建议获取返回结果中最早一条消息的 `sentTime`,并在下一次调用时作为 `recordTime` 的值传入,以便遍历整个会话的消息历史记录。升序查询消息一般可用于跳转到会话页面指定消息位置后需要查询更新的历史消息的场景。
| 参数 | 类型 | 说明 |
|:-----------------|:-----------------------|:-----------------------------------|
| conversationType | [RCConversationType] | 会话类型 |
| targetId | NSString | 会话 ID |
| option | RCHistoryMessageOption | 可配置的参数,包括拉取数量、拉取顺序等 |
| complete | Block | 获取消息的回调 |
- **`RCHistoryMessageOption` 说明**:
| 参数 | 说明 |
|:-----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| recordTime | 时间戳,用于控制分页查询消息的边界。默认值为 `0`。 |
| count | 要获取的消息数量。如果 SDK \< 5.4.1,范围为 [2-20];如果 SDK ≧ 5.4.1,范围为 [2-100];默认值为 `0`,表示不获取。 |
| order | 拉取顺序。`RCHistoryMessageOrderDesc`:降序,按消息发送时间递减的顺序,获取发送时间早于 `recordTime` 的消息,返回的列表中的消息按发送时间从新到旧排列。`RCHistoryMessageOrderAsc`: 升序,按消息发送时间递增的顺序,获取发送时间晚于 `recordTime` 的消息,返回的列表中的消息按发送时间从旧到新排列。默认值为降序。 |
[消息类型概述]: /platform-chat-api/message-about/about-message-types
[免费基础功能]: https://console.rongcloud.cn/agile/formwork/baseService/index
[RCConversationType]: https://doc.rongcloud.cn/apidoc/imlibcore-ios/latest/zh_CN/documentation/rongimlibcore/rcconversationtype?language=objc