已读回执(单聊 / 群聊)

已读回执让发送者知道消息被谁读过:接收方上报已读,服务端记录唯一读者并推送给发送者;单聊展示“已读 / 未读”,群聊展示“n/m”。

语义​

场景展示数据来源
单聊已读 / 未读`sendReadReceipt` 上报后,发送方收到 READ_RECEIPT
群聊已读人数 n / 群成员总数 m`getMessageReadCount` 或 READ_RECEIPT 事件载荷
已读明细已读用户列表(分页)`getMessageReadUsers`
多端同账号各端已读状态一致服务端记录唯一读者;本端读后上报一次即可

sendReadReceipt​

上报已读回执;服务端记录唯一读者并推送给消息发送者。

项值
Swiftfunc 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)
幂等否

参数​

参数类型必填说明
conversationTypeConversationType是会话类型枚举(ConversationType)
targetIdstring是目标会话 ID:单聊为对方 userId,群聊为 groupId,聊天室为 chatroomId
messageIdsstring[]是消息 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可重试说明
1001INVALID_PARAMETER客户端 / 参数 / 权限400否参数错误
1003FORBIDDEN客户端 / 参数 / 权限403否无权限
1004USER_NOT_FOUND客户端 / 参数 / 权限404否用户不存在
3001SDK_NOT_CONNECTEDSDK 本地0是长连接未就绪

getMessageReadCount​

查询消息已读人数。

项值
Swiftfunc getMessageReadCount(messageId: String) async -> RcResult<IMPMessageReadCount>
Objective-C- (void)getMessageReadCountWithMessageId:(NSString *)messageId completion:(void (^)(IMPOSResult *result))completion
传输REST(HTTP)
幂等否

参数​

参数类型必填说明
messageIdstring是消息 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可重试说明
1001INVALID_PARAMETER客户端 / 参数 / 权限400否参数错误
1003FORBIDDEN客户端 / 参数 / 权限403否无权限
1004USER_NOT_FOUND客户端 / 参数 / 权限404否用户不存在

getMessageReadUsers​

查询已读用户明细(分页)。

项值
Swiftfunc 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)
幂等否

参数​

参数类型必填说明
messageIdstring是消息 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可重试说明
1001INVALID_PARAMETER客户端 / 参数 / 权限400否参数错误
1003FORBIDDEN客户端 / 参数 / 权限403否无权限
1004USER_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。