常规集成(无 UI 库)

服务端 API

会话(iOS)

最近更新时间:2020-09-29 14:40:05

展示会话列表

用户在登录 App 后,可以像微信那样展示最近会话列表。整个过程分为拉取会话列表处理更新通知更新 UI 内容(包括未读计数),本文主要介绍这些步骤的详细细节。

拉取会话列表

用户在登录后调用 getConversationList() 拉取本地会话列表做 UI 展示,会话列表是一个 V2TIMConversation 对象的列表,每一个对象都代表一个会话。

由于本地会话可能较多(例如超过500个),一次性全部加载完毕可能会耗时很久,导致界面展示比较慢。为了提升用户体验,getConversationList() 接口支持分页拉取能力:

  1. 首次调用 getConversationList() 接口时,可以指定其参数 nextSeq 为0 ,表示从头开始拉取会话列表,并指定 count 为50,表示一次拉取50个会话对象。
  2. IM SDK 按照从新到旧的顺序拉取会话列表,当首次拉取会话列表成功后,getConversationList() 的回调结果 V2TIMConversationResult 中会包含下次分页拉取的 nextSeq 字段以及会话拉取是否完成的 isFinish 字段:
    • 如果 isFinished 返回 true,表示所有会话已经拉取完成。
    • 如果 isFinished 返回 false ,表示还有更多的会话可以拉取。此时并不意味着要立刻开始拉取“下一页”的会话列表。在常见的通信软件中,分页拉取通常由用户的滑动操作触发的,用户每下拉一次会话列表就触发一次分页拉取。
  3. 当用户继续下拉会话列表时,如果还有更多的会话可以拉取,可以继续调用 getConversationList() 接口,并传入新一轮的 nextSeqcount 参数(数值来自上一次拉取返回的 V2TIMConversationResult 对象)。
  4. 重复执行 步骤3 直至 isFinished 返回 true

显示会话信息

获取到 V2TIMConversation 对象后,即可在 UI 上展示,V2TIMConversation 有如下关键字段常被用于构造会话列表:

字段名称 含义
showName 会话名称:
  • 如果是单聊,此接口会优先返回对方好友备注,若没有备注或者不是好友,则返回对方昵称,若昵称也没有,则返回对方的 UserID。
  • 如果是群聊,会显示群的名称。
faceUrl 会话头像:
  • 如果是单聊,会显示对方的头像。
  • 如果是群聊,会显示群头像。
recvOpt 消息接收选项,一般用于群会话,可以显示该群是否设置了“消息免打扰”模式。
unreadCount 用于显示未读计数,表示有多少条未读消息。
lastMessage 最后一条消息,用于显示会话的消息摘要。

更新会话列表

IM SDK 会在登录成功后、用户上线后、以及断线重连后,自动更新会话列表。更新过程如下:

  • 当有会话更新时,例如新收到一条消息,SDK 会通过 V2TIMConversationListener 中的 onConversationChanged 事件通知您。
  • 当有会话新增时,SDK 会通过 V2TIMConversationListener 中的 onNewConversation 事件通知您。
注意:

为保证会话列表顺序符合最后一条消息的排序原则,您需要根据 lastMessage 中的 timestamp 对数据源重新排序。

示例代码

示例代码将介绍如何拉取、展示和更新会话列表:

// 1. 设置会话监听
[[V2TIMManager sharedInstance] setConversationListener:self];
// 2. 登录
[[V2TIMManager sharedInstance] login:@"yahaha" userSig:@"传入实际的 userSig" succ:^{
    // 3. 先拉取50个本地会话做 UI 展示,nextSeq 第一次拉取传 0
    __weak __typeof(self) weakSelf = self;
    [[V2TIMManager sharedInstance] getConversationList:0 count:50
        succ:^(NSArray<V2TIMConversation *> *list, uint64_t nextSeq, BOOL isFinished) {
        __strong __typeof(weakSelf) strongSelf = weakSelf;
        // 拉取成功,更新 UI 会话列表
        [strongSelf updateConversation:list];
        // 4. 如果会话还没拉取完,按需继续拉取,nextSeq 传上次拉取返回的 nextSeq
        if(!isFinished) {
            [[V2TIMManager sharedInstance] getConversationList:nextSeq count:50
                        succ:^(NSArray<V2TIMConversation *> *list, uint64_t nextSeq, BOOL isFinished) {
                // 拉取成功,更新 UI 会话列表
                [strongSelf updateConversation:list];
            } fail:^(int code, NSString *msg) {
                // 拉取会话列表失败
            }];
        }
    } fail:^(int code, NSString *msg) {
        // 拉取会话列表失败
    }];
} fail:^(int code, NSString *msg) {
    // 登录失败
}];

// 收到会话新增的回调
- (void)onNewConversation:(NSArray<V2TIMConversation*> *) conversationList {
    [self updateConversation:conversationList];
}

// 收到会话更新的回调
- (void)onConversationChanged:(NSArray<V2TIMConversation*> *) conversationList {
    [self updateConversation:conversationList];
}

// 更新 UI 会话列表
- (void)updateConversation:(NSArray *)convList
{
    // 如果 UI 会话列表有更新的会话,就替换,如果没有,就新增
    for (int i = 0 ; i < convList.count ; ++ i) {
        V2TIMConversation *conv = convList[i];
        BOOL isExit = NO;
        for (int j = 0; j < self.uiConvList.count; ++ j) {
            V2TIMConversation *uiConv = self.localConvList[j];
            // UI 会话列表有更新的会话,直接替换
            if ([uiConv.conversationID isEqualToString:conv.conversationID]) {
                [self.uiConvList replaceObjectAtIndex:j withObject:conv];
                isExit = YES;
                break;
            }
        }
        // UI 会话列表没有更新的会话,直接新增
        if (!isExit) {
            [self.uiConvList addObject:conv];
        }
    }
    // 重新按照会话 lastMessage 的 timestamp 对 UI 会话列表做排序
    [self.uiConvList sortUsingComparator:^NSComparisonResult(V2TIMConversation *obj1, V2TIMConversation *obj2) {
        return [obj2.lastMessage.timestamp compare:obj1.lastMessage.timestamp];
    }];
}

删除会话

调用 deleteConversation 接口可以删除某个会话,会话删除不支持多端同步,删除会话时默认删除本地和服务器历史消息,且无法恢复。

草稿箱

在发送消息时,可能会遇到消息尚未编辑完就要切换至其它聊天窗口的情况,这些未编辑完的消息可通过 setConversationDraft 接口保存,以便于回到聊天界面后调用 draftText 继续编辑内容。

注意:

  • 草稿仅支持文本内容。
  • 草稿仅在本地保存,不会存储到服务器,因此不能多端同步,程序卸载重装会失效。

常见问题

1. 最近会话列表的保存数量上限是多少?

本地存储的会话列表没有数量上限,云端存储的会话列表最大数量为100。
如果一个会话长时间没有信息变更,该会话在云端最多保存7天,如需放宽限制,请 联系我们

2. 为什么换了一个手机登录相同帐号后拉取的会话列表不一致?

本地存储的会话和云端存储的会话并不总是一致的,如果用户不主动调用 deleteConversation 接口删除本地的会话,该会话就会一直存在。而云端存储的会话最大只会保存100条,且对于长时间没有信息变更的会话,云端最多保存7天,所以不同的终端本地显示的会话可能会不一样。

3. 为什么会拉取到重复的会话?

调用 getConversationList 接口拉取的会话可能已经通过 onNewConversation 回调接口添加到了 UI 会话列表的数据源中,因此为了避免重复添加同一个会话,您需要在 UI 会话列表数据源中根据 getConversationID 找到相同的会话并做替换。

4. IM SDK 支持会话置顶吗?

IM SDK 并不提供会话置顶功能,但是可以通过封装会话再重排序,可以参考 TUIKit 实现。置顶仅对本机生效,不会保存到服务器上。

目录