iOS

最近会话

更新时间: 2024/03/14 17:08:34

最近会话,即最近联系人列表,记录了与用户最近有过会话的联系人信息,包括联系人帐号、联系人类型、最近一条消息的时间、消息状态、消息内容、未读消息数等信息。

最近会话列表由 SDK 维护并提供查询、监听变化的接口,只要与某个用户或者群组发生聊天,SDK 会自动更新最近会话列表并通知,开发者无需手动更新。

特定场景下,开发者需要手动向最近会话列表中插入一条会话项(即插入一个最近联系人),例如:创建高级群后,SDK 不会更新最近会话,开发者可以在创建群回调中插入一条本地消息,实现在最近会话列表中显示该群的会话项。

最近会话为本地而非漫游。在新设备登录后,最近会话列表会根据当前的漫游消息、离线消息等自动生成。

技术原理

网易云信 NIM SDK 提供 NIMSession 来构造最近会话。

objc//p2p
NIMSession *myFriendSession = [NIMSession session:@"friend user id" type:NIMSessionTypeP2P];

//team
NIMSession *teamSession = [NIMSession session:@"team id" type:NIMSessionTypeTeam];

//do something with session

前提条件

已实现登录 IM

监听最近会话事件

在进行最近会话相关操作前,您可以提前注册监听相关事件。监听后,当最近会话对象或其属性发生变更时,SDK 会更新对应聊天对象的用户资料,并触发最近会话更新通知。

NIMConversationManagerDelegate 提供最近会话相关回调事件:

  • didAddRecentSession:最近会话增加回调。当新增一条消息,并且本地不存在该消息所属的会话时,会触发此回调。
  • didUpdateRecentSession:最近会话更新回调。以下条件均可触发该回调:
    • 当新增一条消息,并且本地存在该消息所属的会话。
    • 所属会话的未读消息清零。
    • 所属会话的最后一条消息被删除或其发送内容发生变化。例如:消息成功发送后,修正发送时间为服务器时间。
  • didRemoveRecentSession:最近会话删除回调。
  • didUpdateUnreadCountDic:未读数更新回调。

示例代码:

objc@interface NTESSessionListViewController()<NIMConversationManagerDelegate>
@end
@implementation NTESSessionListViewController
- (void)dealloc
{
    // 移除Delegate
    [[NIMSDK sharedSDK].conversationManager removeDelegate:self];
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // 注册Delegate
    [[NIMSDK sharedSDK].conversationManager addDelegate:self];
}

- (void)didAddRecentSession:(NIMRecentSession *)recentSession
           totalUnreadCount:(NSInteger)totalUnreadCount
{
    // Your Code
}

- (void)didUpdateRecentSession:(NIMRecentSession *)recentSession
              totalUnreadCount:(NSInteger)totalUnreadCount
{
    // Your Code
}

- (void)didRemoveRecentSession:(NIMRecentSession *)recentSession 
              totalUnreadCount:(NSInteger)totalUnreadCount
{
    // Your Code
}

- (void)didUpdateUnreadCountDic:(NSDictionary *)unreadCountDic
{
    // Your Code
}
@end

创建最近会话

参数 说明
session 会话对象,详见 NIMSession
option 创建最近会话选项,详见 NIMAddEmptyRecentSessionBySessionOption
  • 示例代码:
objc// 创建一条空的最近会话
NIMSession *session = [NIMSession session:@"sessionId" type:NIMSessionTypeP2P];
[[NIMSDK sharedSDK].conversationManager addEmptyRecentSessionBySession:session];
objc// 根据配置项创建一条空的最近会话
NIMSession *session = [NIMSession session:@"sessionId" type:NIMSessionTypeP2P];
NIMAddEmptyRecentSessionBySessionOption *option = [[NIMAddEmptyRecentSessionBySessionOption alloc] init];
[[NIMSDK sharedSDK].conversationManager addEmptyRecentSessionBySession:session option:option];

获取最近会话

获取最近会话列表,一般用于在首页显示。

获取所有最近会话列表

objc//  NIMSessionListViewController.m
- (void)viewDidLoad {
    ...
    NSArray *recentSessions = [NIMSDK sharedSDK].conversationManager.allRecentSessions;
    ...
}
  • 为了保证线程安全,请在主线程调用该方法。
  • 为了避免获取会话数量较大(上万)时耗时较长甚至可能卡主线程,自 v7.0.0 起 NIM SDK 提供会话数据加载完成回调 didLoadAllRecentSessionCompletion。您可以设置初始化参数 NIMSDKConfig 中的 asyncLoadRecentSessionEnabledYES,并监听该回调,当最近会话数据库加载完成时会触发该回调,表示可以调用 allRecentSessions 获取所有最近会话列表。
  • 如果会话数量不大,推荐直接调用 allRecentSessions 获取所有最近会话列表。

过滤指定消息类型的会话列表

对最近会话列表的最后一条消息按照类型进行过滤,例如过滤文本消息,则返回最后一条消息非文本消息的会话列表。

参数 说明
option 过滤最近会话选项,详见 NIMRecentSessionOption
  • 示例代码:
objc// 查询所有最近会话,且返回的最近会话最后一条非通知消息
- (void)getAllRecentSessionTests {
	NIMRecentSessionOption *option = [[NIMRecentSessionOption alloc] init];
	option.filterLastMessageTypes = @[@(NIMMessageTypeNotification)];
	NSArray *sessions = [[NIMKit shareKit].conversationManager allRecentSessionsWithOption:option];
}
  • 通过该方法返回的最近会话均为新对象,最近会话相关的所有回调都不会返回调用该方法返回的会话对象。
  • 当会话数量较大(上万)时,调用该方法获取会话耗时较长。

获取指定的最近会话

通过会话 ID 获取指定会话。

参数 说明
session 会话对象,详见 NIMSession
  • 示例代码:
objcNIMSession *session = [NIMSession session:@"sessionId" type:NIMSessionTypeP2P];
NIMRecentSession *recent = [[NIMSDK sharedSDK].conversationManager recentSessionBySession:session];

更新最近会话

更新最近会话的本地扩展信息。应用场景可以为置顶会话、@ 功能。

参数 说明
ext 扩展信息。
recentSession 最近会话对象,详见 NIMRecentSession
  • 示例代码:
objc// NTESSessionUtil.m
// 以下举例使用扩展字端 ext 实现 @ 功能
+ (void)addRecentSessionAtMark:(NIMSession *)session
{
    // 为会话 recent 添加“有人@你”的的标记
    NIMRecentSession *recent = [[NIMSDK sharedSDK].conversationManager recentSessionBySession:session];
    if (recent)
    {
        NSDictionary *localExt = recent.localExt?:@{};
        NSMutableDictionary *dict = [localExt mutableCopy];
        // 例如,可在扩展字段里使用 "AT_MART" 作为是否 @ 的标识
        [dict setObject:@(YES) forKey:"AT_MARK"];
        [[NIMSDK sharedSDK].conversationManager updateRecentLocalExt:dict recentSession:recent];
    }
}

扩展信息 ext 不会漫游到其他端,且应用层需要保证 NSDictionary 可以转换为 JSON。

消息未读数

获取消息未读数

获取总未读数

  • 接口:

    • allUnreadCount:获取总未读数
    • allUnreadCount::获取总未读数并设置是否需要通知。在 NIMTeamNotifyState 不为 NIMTeamNotifyStateNone 的前提下,设置 notifyYES 后,当总未读数变化时会触发 didUpdateUnreadCountDic 回调通知。
  • 示例代码:

objc// 获取总未读数
NSInteger unreadCount  = [[NIMSDK sharedSDK].conversationManager allUnreadCount];
objc// 获取总未读数并设置是否需要通知
NSInteger unreadCount  = [[NIMSDK sharedSDK].conversationManager allUnreadCount:YES];

获取单个会话的消息未读数

objcNIMRecentSession *recent = [[NIMSDK sharedSDK].conversationManager recentSessionBySession:session];
NSInteger unreadCount = recent.unreadCount;

获取指定类型的会话的消息未读数

参数 说明
type 会话类型。详见 NIMSessionType
  • 示例代码:
NSInteger unreadCount = [[NIMSDK sharedSDK].conversationManager unreadCountOfType:NIMSessionTypeP2P];

该方法只能在主线程调用。

获取指定会话未读消息列表

参数 说明
session 会话对象,详见 NIMSession
completion 获取未读消息异步回调。详见 NIMFetchMessageHistoryBlock
  • 示例代码:
objective-c// 准备待查会话
NIMSession *session = [NIMSession session:@"ios01" type:NIMSessionTypeP2P];

// 同步接口,根指定会话未读消息列表
[[[NIMSDK sharedSDK] conversationManager] allUnreadMessagesInSession:session];

// 异步接口,根指定会话未读消息列表
[[[NIMSDK sharedSDK] conversationManager] allUnreadMessagesInSession:session completion:^(NSError * _Nullable error, NSArray<NIMMessage *> * _Nullable messages) {
        if (error == nil){
            // 获取指定会话未读消息列表成功
            NSLog(@"[All unread messages in session get, message count: %lu]", (unsigned long)messages.count);
            // your code ...
        }else{
            // 获取指定会话未读消息列表失败
            NSLog(@"[NSError with: %@] ", error);
        }
    }];

指定会话的未读数清零(标记已读)

调用以下方法将指定会话中的消息标记为已读,即未读数清零,SDK 会触发最近会话更新回调 onMarkMessageReadCompleteInSession:error:

请根据场景需求对未读数清零,例如当前正在聊天的会话,不需要显示未读数,必须清零。其他情况请谨慎调用该方法。

参数 说明
session 会话对象,详见 NIMSession
completion 未读数清零异步回调。详见 NIMSendACKSessionsBlock
  • 示例代码:
objective-c//  NIMSessionViewController.m
- (void)onRecvMessages:(NSArray *)messages
{
    ....
    //会话页直接监听收到消息后的回调,并由于当前页是在会话,直接认为已读
    if ([session isEqual:self.session])
    {
        //只有当消息所属会话时会话页表示的会话时,才标记已读
        [[NIMSDK sharedSDK].conversationManager markAllMessagesReadInSession:self.session];
    }
    ....
}

批量设置会话未读数清零(标记已读)

调用以下方法将多个会话中的消息标记为已读,即未读数清零,SDK 会触发批量清零会话未读数回调 onBatchMarkMessagesReadInSessions:

参数 说明
sessions 会话对象列表,详见 NIMSession
completion 未读数清零异步回调。详见 NIMSendACKSessionsBlock
  • 示例代码:
objective-c    // 多端同步未读数则需要配置 [[NIMSDKConfig sharedConfig] shouldSyncUnreadCount]  = YES,否则回调会返回配置错误
    // 设置多个会话消息,多使用 allRecentSessions 获取所有最近会话
    NSArray<NIMSession*> *sessions = @[[NIMSession session:@"ios01" type:NIMSessionTypeP2P],
                                       [NIMSession session:@"651146818" type:NIMSessionTypeTeam]];
    // 同步接口,批量设置多个会话消息已读
    [[[NIMSDK sharedSDK] conversationManager] batchMarkMessagesReadInSessions:sessions];

    // 异步接口,批量设置多会话消息已读的回调
    NIMBatchSendACKSessionsBlock block = ^(NSError * __nullable error, NSArray <NIMSession * > * _Nullable sessions)
    {
        if (error == nil){
            // 批量设置多个会话消息已读 成功
            NSLog(@"[Batch mark messages read in sessions. Total %ld failed]", sessions.count);
            // your code ...
        }else{
            // 批量设置多个会话消息已读 失败
            NSLog(@"[NSError with: %@] ", error);
        }
    };
    // 批量设置多个会话消息已读
    [[[NIMSDK sharedSDK] conversationManager] batchMarkMessagesReadInSessions:sessions
                                                                   completion:block];

所有会话未读数清零(标记已读)

调用以下方法将所有会话的消息标记为已读,即未读数清零,SDK 会触发清零所有会话未读数回调 allMessagesRead

objective-c[[NIMSDK sharedSDK].conversationManager markAllMessagesRead];

指定类型的会话未读数清零(标记已读)

调用以下方法将指定类型的会话中的消息标记为已读,即未读数清零,SDK 会触发指定类型会话未读数清零回调 messagesReadOfType:

参数 说明
type 会话类型,详见 NIMSessionType
  • 示例代码:
objective-c// 根据会话类型设置所有会话消息为已读,例如 NIMSessionTypeTeam 为清除所有群聊消息
[[[NIMSDK sharedSDK] conversationManager] markMessagesReadOfType:NIMSessionTypeTeam];

未读数多端同步

设置初始化参数 NIMSDKConfig.shouldSyncUnreadCountYES 开启会话的未读数多端同步后,在一个客户端已读的会话在其它端也会被标记为已读。

objc[NIMSDKConfig sharedConfig].shouldSyncUnreadCount = YES;

删除最近会话

删除指定本地会话

删除指定的本地最近会话,但会保留会话内的消息。调用该方法后,总未读消息数会减去当前会话的未读数。

本地最近会话和服务端会话并不是一一对应的关系,删除最近会话并不会影响服务端会话。

参数 说明
recentSession 最近会话对象,详见 NIMRecentSession
option 删除选项,用于设置是否删除服务端漫游消息及是否标记所有消息为已读,详见 NIMDeleteRecentSessionOption
completion 删除服务端漫游消息异步回调,详见 NIMRemoveRemoteSessionBlock
  • 示例代码:
objective-c// 最近的会话
// NIMRecentSession *recentSession;
// 同步接口,删除某个最近会话
[[[NIMSDK sharedSDK] conversationManager] deleteRecentSession:recentSession];
NSLog(@"[Delete recent session. Session name: %@]", [recentSession.session sessionId]);

// 异步接口,删除某个会话 & 设置
NIMDeleteRecentSessionOption *option = [[NIMDeleteRecentSessionOption alloc] init];
// 是否删除漫游信息
option.isDeleteRoamMessage = YES;
// 删除某个最近会话 回调
NIMRemoveRemoteSessionBlock block = ^(NSError * __nullable error)
{
    if (error == nil){
        // 删除某个最近会话 成功
        NSLog(@"[Delete recent session. Session name: %@]", recentSession.session.sessionId);
        // your code ...
    }else{
        // 删除某个最近会话 失败
        NSLog(@"[NSError with: %@] ", error);
    }
};
// 删除某个最近会话
[[[NIMSDK sharedSDK] conversationManager] deleteRecentSession:recentSession
                                                        option:option
                                                    completion:block];

删除漫游消息

删除指定会话的服务端漫游消息。

参数 说明
sessions 服务端会话列表,详见 NIMRecentSession
completion 删除服务端漫游消息异步回调,详见 NIMRemoveRemoteSessionBlock
  • 示例代码:
objective-c    // 最近会话
    NSArray<NIMSession *> *sessions = @[[NIMSession session:@"ios01" type:NIMSessionTypeP2P]];
    // 删除服务器端最近会话 回调
    NIMRemoveRemoteSessionBlock block = ^(NSError * __nullable error)
    {
        if (error == nil){
            // 删除服务器端最近会话   成功
            NSLog(@"[Delete remote sessions succeed.]");
            // Your code
        }else{
            // 删除服务器端最近会话   失败
            NSLog(@"[NSError with: %@] ", error);
        }
    };
    // 删除服务器端最近会话
    [[[NIMSDK sharedSDK] conversationManager] deleteRemoteSessions:sessions
                                                        completion:block];

调用该接口后,当前会话前的消息都不会漫游到其他端。

若想同时删除服务端的历史消息,请参见删除指定会话的服务端历史消息

此文档是否对你有帮助?
有帮助
去反馈
  • 技术原理
  • 前提条件
  • 监听最近会话事件
  • 创建最近会话
  • 获取最近会话
  • 获取所有最近会话列表
  • 过滤指定消息类型的会话列表
  • 获取指定的最近会话
  • 更新最近会话
  • 消息未读数
  • 获取消息未读数
  • 获取总未读数
  • 获取单个会话的消息未读数
  • 获取指定类型的会话的消息未读数
  • 获取指定会话未读消息列表
  • 指定会话的未读数清零(标记已读)
  • 批量设置会话未读数清零(标记已读)
  • 所有会话未读数清零(标记已读)
  • 指定类型的会话未读数清零(标记已读)
  • 未读数多端同步
  • 删除最近会话
  • 删除指定本地会话
  • 删除漫游消息