SDK 文档

服务端 API

会话(iOS)

最近更新时间:2021-08-02 16:24:30

展示会话列表

用户在登录 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 会话头像:
  • 如果是单聊,会显示对方的头像。
  • 如果是群聊,会显示群头像。
unreadCount 用于显示未读计数,表示有多少条未读消息。
recvOpt 消息接收选项,一般用于群会话,可以显示该群是否设置了“消息免打扰”模式。
lastMessage 最后一条消息,用于显示会话的消息摘要。
groupAtInfolist 会话 @ 信息,用于展示 "有人 @ 我"、"@ ALL" 等信息
isPinned 会话是否置顶,仅精简版本支持

更新会话列表

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];
  }];
}

获取所有会话的未读消息总数(仅精简版 5.3.425 及以上版本支持)

调用 getTotalUnreadMessageCount 接口可以获取所有会话的未读消息总数。您不用再遍历会话列表,把单个会话的未读数相加,才能得到未读总数。当会话的未读总数发生变更的时候,SDK 会主动向您的 App 回调 onTotalUnreadMessageCountChanged ,把最新的未读总数通知给您。

置顶会话(仅精简版 5.3.425 及以上版本支持)

会话置顶指的是把特定的好友或者群会话固定在会话列表的最前面,新版本 SDK 增加了主动设置或者取消会话置顶的接口 pinConversation ,同时支持漫游和多端同步。
会话对象 V2TIMConversation 新增了 isPinned 接口,用于判断会话的置顶状态。当会话的置顶状态发生变更的时候,SDK 会向您的 App 回调 onConversationChanged

删除会话

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

草稿箱

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

注意:

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

常见问题

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

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

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

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

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

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

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

IM SDK 从5.3.425版本开始支持会话置顶功能并可以同步到云端。

目录