已读回执(单聊 / 群聊)
已读回执让发送者知道消息被谁读过:接收方上报已读,服务端记录唯一读者并推送给发送者;单聊展示“已读 / 未读”,群聊展示“n/m”。
语义
| 场景 | 展示 | 数据来源 |
|---|---|---|
| 单聊 | 已读 / 未读 | `sendReadReceipt` 上报后,发送方收到 READ_RECEIPT |
| 群聊 | 已读人数 n / 群成员总数 m | `getMessageReadCount` 或 READ_RECEIPT 事件载荷 |
| 已读明细 | 已读用户列表(分页) | `getMessageReadUsers` |
| 多端 | 同账号各端已读状态一致 | 服务端记录唯一读者;本端读后上报一次即可 |
sendReadReceipt
上报已读回执;服务端记录唯一读者并推送给消息发送者。
| 项 | 值 |
|---|---|
| Swift | func sendReadReceipt(conversationType: IMPConversationType, targetId: String, messageIds: [String]) async -> RcResult<IMPSendReadReceiptResult> |
| Objective-C | - (void)sendReadReceiptWithConversationType:(NSInteger)conversationType targetId:(NSString *)targetId messageIds:(NSArray<NSString *> *)messageIds completion:(void (^)(IMPOSResult *result))completion |
| 传输 | 长连接(WebSocket) |
| 幂等 | 否 |
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
conversationType | ConversationType | 是 | 会话类型枚举(ConversationType) |
targetId | string | 是 | 目标会话 ID:单聊为对方 userId,群聊为 groupId,聊天室为 chatroomId |
messageIds | string[] | 是 | 消息 ID 列表 |
返回
{messageIds:string[], readCounts?:map<string,uint32>, totalMembers?:uint32}:成功返回的数据;失败时按错误码处理
示例(Swift / Objective-C)
let res = await client.sendReadReceipt(conversationType: .privateChat, targetId: "user2", messageIds: ["m_10001"])
if res.code != 0 { print(res.msg ?? "") }[client sendReadReceiptWithConversationType:1 /* 单聊 */ targetId:@"user2" messageIds:@[@"m_10001"] completion:^(IMPOSResult *result) {
if (result.code != 0) { NSLog(@"IM 调用失败:%ld %@", (long)result.code, result.msg); }
}];错误码
| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1003 | FORBIDDEN | 客户端 / 参数 / 权限 | 403 | 否 | 无权限 |
1004 | USER_NOT_FOUND | 客户端 / 参数 / 权限 | 404 | 否 | 用户不存在 |
3001 | SDK_NOT_CONNECTED | SDK 本地 | 0 | 是 | 长连接未就绪 |
getMessageReadCount
查询消息已读人数。
| 项 | 值 |
|---|---|
| Swift | func getMessageReadCount(messageId: String) async -> RcResult<IMPMessageReadCount> |
| Objective-C | - (void)getMessageReadCountWithMessageId:(NSString *)messageId completion:(void (^)(IMPOSResult *result))completion |
| 传输 | REST(HTTP) |
| 幂等 | 否 |
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
messageId | string | 是 | 消息 ID(服务端生成) |
返回
{messageId:string, readCount:uint32, totalMembers:uint32}:已读人数与群成员总数
示例(Swift / Objective-C)
let count = await client.getMessageReadCount(messageId: "m_10001")
print(count.code)[client getMessageReadCountWithMessageId:@"m_10001" completion:^(IMPOSResult *result) {
if (result.code != 0) { NSLog(@"IM 调用失败:%ld %@", (long)result.code, result.msg); }
}];错误码
| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1003 | FORBIDDEN | 客户端 / 参数 / 权限 | 403 | 否 | 无权限 |
1004 | USER_NOT_FOUND | 客户端 / 参数 / 权限 | 404 | 否 | 用户不存在 |
getMessageReadUsers
查询已读用户明细(分页)。
| 项 | 值 |
|---|---|
| Swift | func getMessageReadUsers(messageId: String, options: IMPPageOptions?) async -> RcResult<IMPMessageReadUsers> |
| Objective-C | - (void)getMessageReadUsersWithMessageId:(NSString *)messageId options:(NSDictionary<NSString *, id> * _Nullable)options completion:(void (^)(IMPOSResult *result))completion |
| 传输 | REST(HTTP) |
| 幂等 | 否 |
参数
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
messageId | string | 是 | 消息 ID(服务端生成) |
options | {offset?:uint32, limit?:uint32} | 否 | 选项对象(字段见类型列):{ offset?:uint32, limit?:uint32 } |
返回
{messageId:string, readCount:uint32, totalMembers:uint32, readers:UserProfile[]}:已读用户明细(分页)
示例(Swift / Objective-C)
let users = await client.getMessageReadUsers(messageId: "m_10001", options: nil)
print(users.code)[client getMessageReadUsersWithMessageId:@"m_10001" options:nil completion:^(IMPOSResult *result) {
if (result.code != 0) { NSLog(@"IM 调用失败:%ld %@", (long)result.code, result.msg); }
}];错误码
| 错误码 | 名称 | 分类 | HTTP | 可重试 | 说明 |
|---|---|---|---|---|---|
1001 | INVALID_PARAMETER | 客户端 / 参数 / 权限 | 400 | 否 | 参数错误 |
1003 | FORBIDDEN | 客户端 / 参数 / 权限 | 403 | 否 | 无权限 |
1004 | USER_NOT_FOUND | 客户端 / 参数 / 权限 | 404 | 否 | 用户不存在 |
上报时机
- 进入会话并渲染出消息后上报(不是收到消息就上报)。
- 批量上报:一次传多条 messageIds,减少请求数。
- 滚动到历史消息时,对可见范围内的未读消息补报。
- 上报成功后本地把消息标记为已读,并清零该会话未读(`clearUnreadCount`)。
- 收到 READ_RECEIPT 事件时更新发送方气泡的已读状态。
Swift
let groupRes = await client.sendReadReceipt(conversationType: .group, targetId: "g_1001", messageIds: ["m_10002"])
print(groupRes.code)逐条已读(更细粒度)见 逐条已读;IMKit 展示见 MessageStatusIndicator。