跳到主要内容

单群聊已读回执

已读回执功能可以让发送方知道消息是否被对方已读。

  • 在单聊场景下,当接收方已读消息后,可以主动发送已读回执给发送方,发送方通过监听已读回执消息来获得已读通知。
  • 在群聊场景下,当一条消息发送到群组后,发送方可以在消息发送完成后主动发起已读回执请求。群组中的其他成员在读到这条消息后,可以对请求进行响应。发送方通过监听已读回执响应结果来获知哪些群成员已读了这条消息。

SDK 针对单聊、群聊已读回执相关的事件提供了不同的事件处理机制:

单聊已读回执

单聊已读回执功能基于用户在 1 对 1 会话中上次阅读位置的消息的时间戳。通过将该时间戳传递给对方,对方可获得已发送的消息的阅读进度。SDK 定义了 RCSentStatus,用于记录单聊会话中的一条消息是否已被对方阅读,应用程序可以通过访问本端发出的消息的发送状态(sentStatus)属性查询具体状态。

发送单聊已读回执

消息接收方在阅读过某条消息后,需要主动发送已读回执给发送方。调用 sendReadReceiptMessage:targetId:time:success:error: 方法时需要传入一个时间戳。可以传入指定消息的发送时间(message.sentTime),或者传入会话最后一条消息的发送时间(conversation.sentTime)。

[[RCCoreClient sharedCoreClient]
sendReadReceiptMessage:ConversationType_PRIVATE
targetId:@"targetId"
time:sentTime
success:nil
error:nil];

单聊已读回执实际是一条已读通知消息,由 SDK 内部构建并发出。

接收单聊已读回执

SDK 收到单聊消息的已读回执后,会读取其中携带的时间戳,将本地消息数据库中该单聊会话的早于该时间戳的所有消息的 sentStatus 属性改为 SentStatus_READ,同时 IMLib SDK 会分发一个 RCLibDispatchReadReceiptNotification 的通知。应用程序需要注册为已读回执通知的观察者,才能收取到该类通知。

这段代码将当前对象 (self) 注册为 RCLibDispatchReadReceiptNotification 通知的观察者。当收到此通知时,将调用 didReceiveReadReceiptNotification: 方法。

[[NSNotificationCenter defaultCenter]
addObserver:self
selector:@selector(didReceiveReadReceiptNotification:)
name:RCLibDispatchReadReceiptNotification
object:nil];

didReceiveReadReceiptNotification: 方法在收到读取回执通知时调用。该方法接受一个 NSNotification 对象作为参数。可以使用此对象来获取读取回执通知的信息。

- (void)didReceiveReadReceiptNotification:(NSNotification *)notification {

RCConversationType conversationType = (RCConversationType)[notification.userInfo[@"cType"] integerValue];
long long readTime = [notification.userInfo[@"messageTime"] longLongValue];
NSString *targetId = notification.userInfo[@"tId"];
NSString *senderUserId = notification.userInfo[@"fId"];
}

这段代码从通知的 userInfo 字典中获取以下信息:

  • 会话类型 (conversationType)
  • 读取时间 (readTime)
  • 目标 ID (targetId)
  • 发送者 ID (senderUserId)

上面的 readTime 即单聊已读回执消息中携带的时间戳。此时消息数据库内发送时间小于或等于 readTime 的消息的发送状态属性( sentStatus)均已被改为对方已读(SentStatus_READ)。应用程序在 UI 展示本端已发送的消息时,可以将早于该时间戳的消息均展示为对方已读。

群聊已读回执

群聊已读回执功能基于消息的全局唯一 ID(UID)。通过在群聊会话中传递消息的 UID,消息发送者可获得一条指定消息的阅读进度和已读用户列表。SDK 定义了 RCReadReceiptInfo,用于记录群聊会话中的一条消息群组已读回执数据,应用程序可以通过访问本端发出的消息的 readReceiptInfo 属性查询具体状态。

群聊已读回执的工作流程如下:

  1. 群成员 Alice 往群组发送了一条消息。消息将到达即时通讯服务端,并由即时通讯服务端发送到目标群组中。
  2. Alice 希望得知已阅读该条消息的群成员列表。作为该条消息的发送者,她可以发起群组消息已读回执请求。
  3. 群组中其他成员监听到 Alice 发起的群消息已读回执请求。
  4. 群成员 Bob 阅读了 Alice 发送的群消息,于是在群组中响应 Alice 的已读回执请求。
  5. 作为消息发送者,Alice 可以通过监听接收该条消息的已读回执响应。收到 Bob 在群组中发送的响应后,即可调整消息已读数。

发起群聊已读回执请求

发送者向群组中发送消息后,必须先主动发起已读回执请求,获取群成员的主动响应,才能获取该条消息的阅读状态。在一个群组会话中,只有消息发送者可以发起群聊已读回执请求。

消息发送完成后,消息发送者使用 sendReadReceiptRequest:success:error: 方法,传入已发送的 RCMessage 对象,对这条消息发起已读回执请求,SDK 内部会构建并发出一条群聊已读回执请求消息。

[[RCCoreClient sharedCoreClient] sendReadReceiptRequest:message
success:^{
}error:^(RCErrorCode nErrorCode) {
}];

接收群聊已读回执请求

SDK 在接收消息的委托协议 RCIMClientReceiveMessageDelegate 中定义了与群聊已读回执的相关代理方法。

应用程序可以通过 addReceiveMessageDelegate 方法设置多个消息接收代理。

[[RCCoreClient sharedCoreClient] addReceiveMessageDelegate:self];

在任意群成员发起已读回执请求后,其他群成员会通过 RCIMClientReceiveMessageDelegateonMessageReceiptRequest 代理方法收到已读回执请求。

/*!
请求消息已读回执(收到需要阅读时发送回执的请求,收到此请求后在会话页面已经展示该 messageUId 对应的消息或者调用
getHistoryMessages 获取消息的时候,包含此 messageUId 的消息,需要调用 sendMessageReadReceiptResponse
接口发送消息阅读回执)

@param messageUId 请求已读回执的消息ID
@param conversationType conversationType
@param targetId targetId
*/
- (void)onMessageReceiptRequest:(RCConversationType)conversationType
targetId:(NSString *)targetId
messageUId:(NSString *)messageUId;

onMessageReceiptRequest 方法中会返回消息的 UID,您可以通过 getMessageByUId:completion: 方法获取消息对象,用于后续响应已读回执请求。如果需要批量获取消息,可以使用 RCChannelClient 下的 getBatchLocalMessages:targetId:channelId:messageUIDs:success:error: 方法。

响应群聊已读回执请求

应用程序可以根据用户的阅读进度,对已读回执请求进行响应。如果一次接收到多个请求,可以批量响应已读回执请求,但一次只能批量响应同一个会话中的已读回执请求。

使用 sendReadReceiptResponse:targetId:messageList:success:error: 方法,传入会话类型、群组 ID 和 RCMessage 对象列表,发起已读回执响应。注意会话类型一定是 ConversationType_GROUP

[[RCCoreClient sharedCoreClient] sendReadReceiptResponse:ConversationType_GROUP
targetId:@"targetId"
messageList:msgList
success:^{

}
error:^(RCErrorCode nErrorCode){

}];

接收群聊已读回执响应

群组内有用户响应成功后,请求发起方会通过 RCIMClientReceiveMessageDelegateonMessageReceiptResponse 收到通知及响应结果。注意只有请求发起者可以收到响应。

/*!
消息已读回执响应(收到阅读回执响应,可以按照 messageUId 更新消息的阅读数)
@param messageUId 请求已读回执的消息ID
@param conversationType RCConversationType
@param targetId targetId
@param userIdList 已读userId列表,字典类型 key:userId,value:readTime,例如:{"uid100001":1683708891523}
*/
- (void)onMessageReceiptResponse:(RCConversationType)conversationType
targetId:(NSString *)targetId
messageUId:(NSString *)messageUId
readerList:(NSMutableDictionary *)userIdList;

应用程序可以从 onMessageReceiptResponse 方法中获取消息的 UID 和所有已响应的用户列表。在 UI 展示本端发送的该条消息时,可以展示已读人数和具体的已读用户列表。SDK 会在消息的 readReceiptInf)属性中存储该条群聊消息的已读回执数据。