logo
当前页

在聊天页面中渲染对话消息


功能简介

本文介绍了如何使用 ZIM SDK 在基本的聊天页面中渲染消息。

前提条件

已在项目中集成了 ZIM SDK 并实现了基本收发消息的功能,详情请参考 快速开始 - 实现基本收发消息

消息数据来源概述

页面上需要渲染的消息数据来源主要有以下几种:

  1. 历史对话消息: 首次进入聊天页面和查看历史消息时,需要查询历史对话消息并渲染到聊天界面。
  2. 实时收到的消息: 实时收到的聊天消息需要渲染到聊天界面。
  3. 本地发送的消息: 本地发送的聊天消息(包含发送中、发送成功、发送失败等状态)需要渲染到聊天界面。

获取消息数据渲染到聊天界面

以单聊会话为例,跳转到聊天页面时,需要保存对应单聊的 conversationID(对方的 userID)并维护一个用于保存当前会话的消息列表 myMessageList

在获取消息数据时建议实现 addMessage 工具方法用于合并历史消息、实时接收的消息和本地发送的消息。

// 有新消息时,通过该方法将消息更新到消息列表中
- (void)addMessage:(NSArray<ZIMMessage *> *)addList {
    if (!addList || addList.count == 0) return;
    
    NSMutableArray<ZIMMessage *> *mutableList = [self.myMessageList mutableCopy];
    if (!mutableList) {
        mutableList = [NSMutableArray array];
    }
    
    for (ZIMMessage *newMsg in addList) {
        BOOL replaced = NO;
        for (NSInteger i = 0; i < mutableList.count; i++) {
            ZIMMessage *oldMsg = mutableList[i];
            if ((newMsg.messageID && oldMsg.messageID && [newMsg.messageID isEqualToString:oldMsg.messageID]) ||
                (newMsg.localMessageID && oldMsg.localMessageID && [newMsg.localMessageID isEqualToString:oldMsg.localMessageID])) {
                // 替换已有消息
                mutableList[i] = newMsg;
                replaced = YES;
                break;
            }
        }
        if (!replaced) {
            [mutableList addObject:newMsg];
        }
    }
    
    // 根据 orderKey 从小到大排序
    [mutableList sortUsingComparator:^NSComparisonResult(ZIMMessage *msg1, ZIMMessage *msg2) {
        if (msg1.orderKey < msg2.orderKey) return NSOrderedAscending;
        if (msg1.orderKey > msg2.orderKey) return NSOrderedDescending;
        return NSOrderedSame;
    }];
    
    self.myMessageList = [mutableList copy];
}
说明

每次调用消息相关的接口时(比如以下展示的接口),会得到一个消息列表 ZIMMessage[]。获得的消息列表需要进行合并数据的操作,从而得到一个无重复消息、有序的消息列表用于在消息页面进行渲染。消息排序规则为根据 ZIMMessage 中的 orderkey 属性进行排序(orderkey 越大表示当前消息越新);去重规则为根据消息的 localMessageID 判断消息对象是否为同一条消息,重复时新数据替换旧数据。

查询历史消息并渲染到聊天界面

调用 queryHistoryMessageByConversationID 接口从新分页到旧分页(按时间顺序从最近的消息到更久之前的消息)进行查询,获取双方的历史消息并渲染到聊天界面。

ZIMMessageQueryConfig *queryConfig = [[ZIMMessageQueryConfig alloc] init];
queryConfig.count = 20;//
queryConfig.nextMessage = nil;//首次查询时传空,需要更多历史消息时,传入消息列表中最早的消息再次调用
[zim queryHistoryMessageByConversationID:myConversationID 
            conversationType:ZIMConversationTypePeer 
            config:queryConfig 
            callback:callback:^(NSString * _Nonnull conversationID, ZIMConversationType conversationType, NSArray<ZIMMessage *> * _Nonnull messageList, ZIMError * _Nonnull errorInfo){
    [self addMessage:messageList];            
    // update UI
}];

ZIMMessageQueryConfig queryConfig;
queryConfig.count = 20;
queryConfig.nextMessage = nullptr; // 首次查询为空

zim->queryHistoryMessage(
    myConversationID,
    ZIMConversationType::Peer,
    queryConfig,
    [this](const std::string& conversationID, ZIMConversationType type,
           const std::vector<ZIMMessage>& messageList, const ZIMError& errorInfo) {
        addMessage(messageList);
        refreshUI(); // 自定义 UI 刷新函数
    });
    

获取实时接收的消息并渲染到聊天界面

监听 peerMessageReceived 接口获取实时接收的消息,并渲染到聊天界面。


- (void)zim:(ZIM *)zim
    peerMessageReceived:(NSArray<ZIMMessage *> *)messageList
                   info:(ZIMMessageReceivedInfo *)info
             fromUserID:(NSString *)fromUserID{
     if(fromUserID != myConversationID){
         return;// 非当前会话收到的聊天消息,忽略
     }
     [self addMessage: messageList];
     // update UI
 }

将本地发送的消息渲染到聊天界面

监听 messageSentStatusChanged ,获取本地发送消息的发送状态的变化(发送中、发送成功、发送失败),渲染本地发送的消息及其发送状态到聊天界面。

- (void)zim:(ZIM *)zim
    messageSentStatusChanged:
        (NSArray<ZIMMessageSentStatusChangeInfo *> *)messageSentStatusChangeInfoList{
       for(ZIMMessageSentStatusChangeInfo *info in messageSentStatusChangeInfoList){
           if(info.message.conversationID != myConversationID){
               continue;
           }
           [self addMessage:info.message];
       }
       // update UI
}

通过以上方式,即可实现在聊天页面中渲染历史消息、实时接收的消息和本地发送的消息(包含发送状态)。

Previous

订阅用户在线状态

Next

迁移方案

当前页

返回到顶部