文档中心
IM 即时通讯
文档中心
体验 App
SDK 中心
API 中心
常见问题
代码市场
进入控制台
立即注册
登录
中文站 English
  • 文档中心
  • 即时通讯
  • 消息相关
  • 回复消息

回复消息

更新时间:2024-11-11 09:39

功能简介

ZIM SDK 支持会话内回复消息功能,即引用接收到的某一条消息进行针对性的回复,形成起始于该消息的消息回复树状结构。通过此功能,用户可针对某一条消息进行提问、反馈或补充相关背景信息。

概念解释

本功能涉及概念如下:

  • 根消息:回复树的起点,通常是某个特定讨论的起始消息。
  • 子消息:是指对某条消息的直接或间接回复。
  • 源消息:是指某条回复的上一级消息。
  • 回复数:根消息收到的回复数量。

以群聊会话消息 A、B 和 C 为例:

  1. 消息 B 回复了消息 A,则:
    • 消息 A 是根消息。
    • 消息 A 是消息 B 的源消息。
    • 消息 B 是消息 A 的子消息。
  2. 消息 C 回复了消息 B,则:
    • 消息 B 为消息 C 的源消息,
    • 消息 C 是消息 B 的子消息。
  3. 消息 B 和消息 C 都是消息 A 的子消息。
  4. 消息 A 的回复数是 2。消息 B 没有回复数。

前提条件

在实现“回复消息”功能之前,请确保:

  • 已在 ZEGO 控制台 创建项目,获取到了接入 ZIM SDK 服务所需的 AppID、AppSign。ZIM 服务权限不是默认开启的,使用前,请先在 ZEGO 控制台 自助开通 ZIM 服务(详情请参考控制台的 服务配置 - 即时通讯 - 开通服务),若无法开通 ZIM 服务,请联系 ZEGO 技术支持开通。
  • 已集成 ZIM SDK,详情请参考 快速开始 - 实现基本收发消息 的 “2 集成 SDK”。

回复一条消息

登录 ZIM 后,用户可以监听 peerMessageReceived 和 groupMessageReceived 回调接收单聊会话和群聊会话的新消息,或调用 queryHistoryMessageByConversationID 接口拉取历史消息。

此时,用户可以选择其中某条消息进行回复,即将该消息作为 toOriginalMessage 参数,并构造一个消息作为回复内容作为 message 参数,调用 replyMessage 接口。

上述 toOriginalMessage 和 message 都仅支持以下类型:

  • 文本消息:ZIMTextMessage(1)
  • 图片消息:ZIMImageMessage(11)
  • 文件消息:ZIMFileMessage(12)
  • 音频消息:ZIMAudioMessage(13)
  • 视频消息:ZIMVideoMessage(14)
  • 合并消息:ZIMCombineMessage(100)
  • 自定义消息:ZIMCustomMessage(200)

除了上述必要参数之外,您还可以根据业务需求构造 notification 对象,监听如下回调:

  • onMessageAttached:在回复发送前,可以获得一个临时的 ZIMMessage,以便您添加一些业务处理逻辑。
  • onMediaUploadingProgress:当发送包含富媒体的消息时,此回调将提供文件上传进度的更新。

发送结果将通过 ZIMMessageSentCallback 返回。

// 回复消息内容
ZIMTextMessage *textMessage = [[ZIMTextMessage alloc] init];
textMessage.message = @"消息内容";

ZIMMessageSendConfig *config = [[ZIMMessageSendConfig alloc] init];
// 设置消息优先级
config.priority = ZIMMessagePriorityLow;

ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
    // 发送前的回调,客户可以在这里获取一个临时对象,该对象与开发者创建的 zimMessage 对象属于同一对象,开发者可利用此特性做一些业务逻辑,如提前展示 UI 等
};
notification.onMediaUploadingProgress = ^(ZIMMediaMessage * _Nonnull message, unsigned long long currentFileSize, unsigned long long totalFileSize) {
    // 若发送的回复消息为媒体消息,则可以监听媒体附件的上传进度
};

// 回复一条消息,引用的源消息对象 toOriginalMessage 可以通过 queryHistoryMessageByConversationID 或者 peerMessageReceived 和 groupMessageReceived 获取。
[[ZIM getInstance] replyMessage:textMessage toOriginalMessage:toOriginalMessage config:config notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
    // 开发者可以通过该回调监听消息是否发送成功。
}];

判断消息是否回复其他消息

监听 peerMessageReceived 和 groupMessageReceived 回调在单聊会话和群聊会话中收到新消息后,需要通过判断消息是否存在 repliedInfo(源消息基本信息):

  • 如果存在,则表示这条消息是对其他消息的回复。
  • 如果不存在,则表示这条消息是一条独立消息。

当您获取到 repliedInfo,可用于展示源消息的发送用户、发送时间和消息内容等。

//注册 ZIMEventHander 回调
[zim setEventHandler:self];

// 收到单聊消息的回调
- (void)zim:(ZIM *)zim
    peerMessageReceived:(NSArray<ZIMMessage *> *)messageList
                   info:(ZIMMessageReceivedInfo *)info
             fromUserID:(NSString *)fromUserID {
     for(ZIMMessage *message in messageList) {
         if(message.repliedInfo) {
           // 此回复消息引用的源消息的基本信息,用于展示源消息的发送者、发送时间、消息内容等
         }
     }   
}

// 收到群组消息的回调
- (void)zim:(ZIM *)zim
    groupMessageReceived:(NSArray<ZIMMessage *> *)messageList
                    info:(ZIMMessageReceivedInfo *)info
             fromGroupID:(NSString *)fromGroupID {
    for(ZIMMessage *message in messageList) {
         if(message.repliedInfo) {
           // 此回复消息引用的源消息的基本信息,用于展示源消息的发送者、发送时间、消息内容等
         }
     }  
}

获取根消息回复数

ZIM 支持主动或被动获取某条根消息的回复数。

主动获取

如需主动获取某条根消息的回复数,可直接通过 ZIMMessage > rootRepliedCount 获取。

被动获取

如需实时了解根消息收到了多少条回复,您可以监听 messageRepliedCountChanged。

//注册 ZIMEventHander 回调
[zim setEventHandler:self];

// 监听根消息的回复数量变化
// 事件触发时机:当有新的消息回复成功后,其回复树的根消息的回复数量会增加 1
- (void)zim:(ZIM *)zim messageRepliedCountChanged:(NSArray<ZIMMessageRootRepliedCountInfo *> *)infos {
    // 更新会话的对应 messageID 的消息的 rootRepliedCount
}

监听源消息被删除或撤回

监听 messageRepliedInfoChanged 回调,即可在某条消息被删除或被撤回时,获取该消息的下一级子消息列表,您可以在相关子消息 UI 上展示相关提示。

即使用户在某设备删除源消息,导致子消息的 repliedInfo.state(其源消息的状态)为 ZIMMessageRepliedInfoStateDeleted,依然可以在子消息的 repliedInfo.messageInfo 中获取到源消息的简要内容。因此,开发者可按需选择是否在该设备展示该源消息内容。

//注册 ZIMEventHander 回调
[zim setEventHandler:self];

// 监听回复消息的源消息变更事件
// 事件触发时机:当源消息被 “删除” 和 “撤回” 后,引用其的回复消息的 repliedInfo 属性会发生改变
- (void)zim:(ZIM *)zim messageRepliedInfoChanged:(NSArray<ZIMMessage *> *)messageList {
    for(ZIMMessage *message in messageList) {
        if(message.repliedInfo.state == ZIMMessageRepliedInfoStateDeleted) {
            // 此回复消息引用的源消息被删除,此时可展示为“消息被删除”
        } else if (message.repliedInfo.messageInfo.type == ZIMMessageTypeRevoke) {
            // 此回复消息引用的源消息被撤回,此时可展示为“消息已撤回”
        }
    }
}

查询回复列表

调用 queryMessageRepliedListByMessage,传入根消息或任意回复,即可查看完整的回复列表,了解回复相关的完整消息列表。

本接口返回的结果将区分根消息(rootRepliedInfo)和回复列表(messageList),回复列表会按照回复的发送时间从前往后排序。

ZIMMessageRepliedListQueryConfig *config = [[ZIMMessageRepliedListQueryConfig alloc] init];
config.count = 10; // 查询数量,上限请勿超过 100
config.nextFlag = 0; // 分页标志,首次查询填 0,后续查询以查询结果返回的 nextFlag 为准

// replyMessage 可为根消息或任意一条回复链上的消息,一般通过 queryHistoryMessageByConversationID 接口或者 peerMessageReceived 和 groupMessageReceived 获取
[[ZIM getInstance] queryMessageRepliedListByMessage:replyMessage config:config callback:^(NSArray<ZIMMessage *> * _Nonnull messageList, long long nextFlag, ZIMMessageRootRepliedInfo * _Nonnull rootRepliedInfo, ZIMError * _Nonnull errorInfo){
        if(errorInfo.code == ZIMErrorCodeSuccess) {
            // 查询成功
            // nextFlag 不为 0,表示还有数据,可继续分页查询
            // rootRepliedInfo 为根消息信息
            // messageList 表示对根消息的回复列表。
        } else {
            // 查询失败
        }
}];
  • 查询消息回复列表时,只要是同一个回复树上的消息对象,无论是传其根消息对象还是任一消息对象,只要 nextFlag 填 0 就是从根消息开始按消息发送时间升序查询;
  • 由于 rootRepliedInfo 中的 message 是可空的对象,当 state 为 ZIMMessageRepliedInfoStateDeleted 时,代表根消息已被删除,此时开发者应在 UI 上提示 “根消息已被删除”;当 state 为 ZIMMessageRepliedInfoStateNotFound 时,代表无法再找到该条根消息,可能原因是消息已超出服务端存储时间,或者群组用户进群后查询回复列表但根消息是其进群前发的,因此该消息可能已不能再拉取,此时开发者应在 UI 上提示 “根消息已无法定位” 等提示性语句。

查看源消息的上下文

由于子消息(即作为回复的消息)的 repliedInfo 仅包含可用于 UI 展示的基本源消息数据,用户可能需要前往源消息的原文位置,阅读源消息附近的其他消息。

因此,如需实现此场景,需要借助子消息的 repliedInfo.messageSeq(源消息在会话中的序号)属性。

子消息的 repliedInfo.messageSeq(源消息在会话中的序号)属性,对应源消息的 messageSeq。

根据源消息及其附近消息是否缓存于应用内存,ZIM 提供了两种实现方案。

源消息及其附近均缓存于应用内存

当某条源消息及其上下文消息都保存于您应用的内存中时(比如,此前以调用 queryHistoryMessage 获取并缓存了会话历史消息),您可在内存检索该源消息的 messageSeq,自行实现前往源消息原文位置查看上下文的业务逻辑。

源消息或其附近的消息没有缓存于应用内存

当应用内存中没有源消息或其附近的消息时,此时,会话中若有其他用户回复了该源消息,即可:

  1. 从该消息的 repliedInfo.messageSeq 获取到源消息的 messageSeq 并作为参数,传入 queryMessagesByMessageSeqs 获取源消息的完整 ZIMMessage 对象。

    // messageSeq 为源消息的在会话中的序号
    NSArray *messageSeqs = @[@(messageSeq)];
    [[ZIM getInstance] queryMessagesByMessageSeqs:messageSeqs conversationID:@"YOUR_CONVERSATION_ID" conversationType:conversationType callback:^(NSString *conversationID, ZIMConversationType conversationType, NSArray<ZIMMessage *> *messageList, ZIMError *errorInfo) {
        if(error.code == ZIMErrorCodeSuccess) {
            // 查询成功
        } else {
            // 查询失败
        }
    }];
  2. 将源消息对象作为 nextMessage 参数,传入 queryHistoryMessageByConversationID,即可以该源消息为锚点,从该源消息往前或往后获取其附近的消息列表,用于 UI 渲染。

    // 本示例以源消息往后查询为例
    ZIMMessageQueryConfig *config = [[ZIMMessageQueryConfig alloc] init];
    // originalMessage 为通过 queryMessagesByMessageSeqs 获取到的源消息对象
    config.nextMessage = originalMessage;
    config.count = 20;
    config.reverse = NO;
    [[ZIM getInstance] queryHistoryMessageByConversationID:@"YOUR_CONVERSATION_ID" conversationType:conversationType config:config callback:^(NSString *conversationID, ZIMConversationType conversationType, NSArray<ZIMMessage *> *messageList, ZIMError *errorInfo) {
        if(error.code == ZIMErrorCodeSuccess) {
            // 查询成功
        } else {
            // 查询失败
        }
    }];
本篇目录
  • 免费试用
  • 提交工单
    咨询集成、功能及报价等问题
    电话咨询
    400 1006 604
    咨询客服
    微信扫码,24h在线

    联系我们

  • 文档反馈