最近会话
更新时间: 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
创建最近会话
-
接口:
- addEmptyRecentSessionBySession::创建一条空的最近会话
- addEmptyRecentSessionBySession:option::根据配置项创建一条空的最近会话
-
参数说明:
参数 | 说明 |
---|---|
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
中的asyncLoadRecentSessionEnabled
为YES
,并监听该回调,当最近会话数据库加载完成时会触发该回调,表示可以调用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
的前提下,设置notify
为YES
后,当总未读数变化时会触发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.shouldSyncUnreadCount
为 YES
开启会话的未读数多端同步后,在一个客户端已读的会话在其它端也会被标记为已读。
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];
调用该接口后,当前会话前的消息都不会漫游到其他端。
若想同时删除服务端的历史消息,请参见删除指定会话的服务端历史消息。