最近会话
更新时间: 2022/09/16 16:20:16
功能概述
会话NIMSession
SDK 中的会话,用 NIMSession
来表示。会话有单人会话,群组会话,聊天室会话等类型。
原型
@interface NIMSession : NSObject<NSCopying>
/**
* 会话ID,如果当前session为team,则sessionId为teamId,如果是P2P则为对方帐号
*/
@property (nonatomic,copy,readonly) NSString *sessionId;
/**
* 会话类型,当前仅支持P2P,Team和Chatroom
*/
@property (nonatomic,assign,readonly) NIMSessionType sessionType;
/**
* 通过id和type构造会话对象
*
* @param sessionId 会话ID
* @param sessionType 会话类型
*
* @return 会话对象实例
*/
+ (instancetype)session:(NSString *)sessionId
type:(NIMSessionType)sessionType;
@end
在使用NIMSession
的时候,不需要去 SDK 获取会话对象,直接根据已有的会话 Id 和 类型构造出即可。示例:
//p2p
NIMSession *myFriendSession = [NIMSession session:@"friend user id" type:NIMSessionTypeP2P];
//team
NIMSession *teamSession = [NIMSession session:@"team id" type:NIMSessionTypeTeam];
//do something with session
本地最近会话
本地最近会话用于表示最近联系人的数据模型。当用户发送,收取消息等,都会同时去修改最近会话。
当收到新联系人的消息时,SDK会自动生成这个消息对应的本地最近会话。但值得注意的是本地最近会话和会话并不是一一对应的关系,删除最近会话并不会影响会话。
本地最近会话在 SDK 中用 NIMRecentSession
表示
/**
* 最近会话
*/
@interface NIMRecentSession : NSObject
/**
* 当前会话
*/
@property (nullable,nonatomic,readonly,copy) NIMSession *session;
/**
* 最后一条消息
*/
@property (nullable,nonatomic,readonly,strong) NIMMessage *lastMessage;
/**
* 未读消息数,为保证线程安全,请在主线程中获取
*/
@property (nonatomic,readonly,assign) NSInteger unreadCount;
/**
* 本地扩展
*/
@property (nullable,nonatomic,readonly,copy) NSDictionary *localExt;
@end
属性列表
参数 | 类型 | 说明 |
---|---|---|
session | NIMSession | 表示的当前会话 |
lastMessage | NIMMessage | 当前会话的最后一条消息 |
unreadCount | NSInteger | 未读消息数,为保证线程安全,请在主线程中获取 |
localExt | NSDictionary | 最近会话的本地扩展,修改后,需要调用 NIMConversationManagerProtocol 中 updateRecentLocalExt:recentSession: 方法,才可以存储到本地 |
获取最近会话
获取最近会话列表
获取最近会话列表,一般用于首页显示会话列表
原型
@protocol NIMConversationManager <NSObject>
/**
* 获取所有最近会话
* @discussion 只能在主线程调用
* @return 最近会话列表
*/
- (nullable NSArray<NIMRecentSession *> *)allRecentSessions;
@end
示例
// NIMSessionListViewController.m
- (void)viewDidLoad {
...
NSArray *recentSessions = [NIMSDK sharedSDK].conversationManager.allRecentSessions;
...
}
为了保证线程安全,这个方法只能在主线程调用,并且由于最近会话在内部是以字典形式存储的,在取出时,会对其进行排序,在数据量过万的情况下会有一定的耗时。
针对最近会话数量过多的情况,从 v7.0.0版本开始,SDK 提供 异步加载完成回调;
@protocol NIMConversationManagerDelegate <NSObject>
/**
* 最近会话数据库读取完成
*
* @discussion 所有最近会话读取完成。设置NIMSDKConfig中的asyncLoadRecentSessionEnabled属性为YES时,此回调会执行。
* 该回调执行表示最近会话全部加载完毕可以通过allRecentSessions来取全部对话。
*/
- (void)didLoadAllRecentSessionCompletion;
@end
注意:
- 需要同时设置
NIMSDKConfig
的asyncLoadRecentSessionEnabled
属性为YES
。 - 本地会话较多,处理耗时较长的情况下:SDK正在查询会话 > 开发者调用allRecentSessions > 此时SDK尚未返回全部会话 > SDK查询完全部会话 > SDK回调-didLoadAllRecentSessionCompletion > 开发者再次调用allRecentSessions获取全量会话并更新UI。
- 本地会话较少的情况下,当开发者调用allRecentSessions时,如果SDK已经返回全部会话,则不会触发该回调。
获取最近会话列表(自定义)
调用allRecentSessionsWithOption
方法,同时设置NIMRecentSessionOption
类下的filterLastMessageTypes
参数,可对最近会话的最后一条消息的类型进行筛选过滤,最终返回最后一条消息为非过滤类型的最近会话列表。
- 通过该方法返回的最近会话均为新对象,最近会话的所有回调都不会返回调用该方法返回的会话。
- 该方法仅适合需要对会话列表最后一条消息类型进行过滤的情况下使用,且数据量较大(上万)时,返回会比较耗时。常规情况下请使用
allRecentSessions
方法获取最近会话列表。
接口原型
@protocol NIMConversationManager <NSObject>
/**
* 获取所有最近会话
* @return 最近会话列表
* @discussion SDK 以 NSArray 的形式保存最近会话,调用这个方法时将进行排序,数据量较大 (上万) 时会比较耗时。
* 通过该接口获取的最近会话列表与allRecentSessions接口不同,是基于allRecentSessions接口筛选类型之后重新生成的新对象
* 需要用户自行在外部管理,所有回调不回回调该接口查询的任何会话
*/
- (nullable NSArray<NIMRecentSession *> *)allRecentSessionsWithOption:(NIMRecentSessionOption *)option;
示例代码
// 查询所有最近会话,且返回的最近会话最后一条非通知消息
- (void)getAllRecentSessionTests {
NIMRecentSessionOption *option = [[NIMRecentSessionOption alloc] init];
option.filterLastMessageTypes = @[@(NIMMessageTypeNotification)];
NSArray *sessions = [[NIMKit shareKit].conversationManager allRecentSessionsWithOption:option];
}
获取指定的最近会话
v5.9.0版本开始,支持通过会话id获取对应的会话。
@protocol NIMConversationManager <NSObject>
/**
* 根据当前 session 返回对应的最近会话信息
*/
- (nullable NIMRecentSession *)recentSessionBySession:(NIMSession *)session
@end
创建最近会话
SDK支持创建最近会话:
- 原型
无配置项版
@protocol NIMConversationManager <NSObject>
/**
* 增加某个最近会话
*
* @param session 待增加的最近会话
* @discussion 异步方法
*/
- (void)addEmptyRecentSessionBySession:(NIMSession *)session;
@end
有配置项版
@protocol NIMConversationManager <NSObject>
/**
* 增加某个最近会话
*
* @param session 待增加的最近会话
* @param option 配置项
* @discussion 异步方法
*/
- (void)addEmptyRecentSessionBySession:(NIMSession *)session option:(NIMAddEmptyRecentSessionBySessionOption *) option;
@end
NIMAddEmptyRecentSessionBySessionOption原型
@interface NIMAddEmptyRecentSessionBySessionOption : NSObject
/**
* 是否填入最后一条消息
* @discussion ,默认为 NO,仅创建空会话;为YES,将同时添加最后一条消息
*/
@property (nonatomic,assign) BOOL withLastMsg;
/**
* 如果没有最后一条消息,是否用一条空消息补位
* @discussion ,默认为 YES,创建一条空消息补位;为NO,不使用补位消息
*/
@property (nonatomic,assign) BOOL addEmptyMsgIfNoLastMsgExist;
@end
更新最近会话
最近会话提供本地扩展能力,可以用来开发 @
以及 置顶
等功能。
原型
@protocol NIMConversationManager <NSObject>
/**
* 更新最近会话的本地扩展
*
* @param ext 扩展信息
* @param recentSession 要更新的最近会话
* @discussion 此扩展不会漫游到其他端,上层需要保证 NSDictionary 可以转换为 JSON。
*/
- (void)updateRecentLocalExt:(nullable NSDictionary *)ext
recentSession:(NIMRecentSession *)recentSession;
@end
属性列表
参数 | 类型 | 说明 |
---|---|---|
ext | NSDictionary | 扩展信息,上层需要保证能将 NSDictionary 转换为 JSON |
recentSession | NIMRecentSession | 要更新的最近会话 |
示例
// NTESSessionUtil.m
+ (void)addRecentSessionAtMark:(NIMSession *)session
{
//为会话添加 有人@你 的的标记
NIMRecentSession *recent = [[NIMSDK sharedSDK].conversationManager recentSessionBySession:session];
if (recent)
{
NSDictionary *localExt = recent.localExt?:@{};
NSMutableDictionary *dict = [localExt mutableCopy];
[dict setObject:@(YES) forKey:NTESRecentSessionAtMark];
[[NIMSDK sharedSDK].conversationManager updateRecentLocalExt:dict recentSession:recent];
}
}
监听最近会话变更
NIMConversationManagerDelegate
提供了最近会话的三个回调通知上层:
分别为增加,修改,删除最近会话的回调:
@protocol NIMConversationManagerDelegate <NSObject>
/**
* 增加最近会话的回调
*
* @param recentSession 最近会话
* @param totalUnreadCount 目前总未读数
* @discussion 当新增一条消息,并且本地不存在该消息所属的会话时,会触发此回调。
*/
- (void)didAddRecentSession:(NIMRecentSession *)recentSession
totalUnreadCount:(NSInteger)totalUnreadCount;
/**
* 最近会话修改的回调
*
* @param recentSession 最近会话
* @param totalUnreadCount 目前总未读数
* @discussion 触发条件包括: 1.当新增一条消息,并且本地存在该消息所属的会话。
* 2.所属会话的未读清零。
* 3.所属会话的最后一条消息的内容发送变化。(例如成功发送后,修正发送时间为服务器时间)
* 4.删除消息,并且删除的消息为当前会话的最后一条消息。
*/
- (void)didUpdateRecentSession:(NIMRecentSession *)recentSession
totalUnreadCount:(NSInteger)totalUnreadCount;
/**
* 删除最近会话的回调
*
* @param recentSession 最近会话
* @param totalUnreadCount 目前总未读数
*/
- (void)didRemoveRecentSession:(NIMRecentSession *)recentSession
totalUnreadCount:(NSInteger)totalUnreadCount;
@end
属性列表
参数 | 类型 | 说明 |
---|---|---|
recentSession | NIMRecentSession | 产生变化的最近会话 |
totalUnreadCount | NSInteger | 目前总未读数 |
此外,还增加了最近会话按会话类型未读数变化的回调。
@protocol NIMConversationManagerDelegate <NSObject>
/**
* 未读数更新的回调 (markRead不会走此回调)
*
* @param unreadCountDic 各类型未读数的字典: [@(NIMSessionType): @(条数)]
*/
- (void)didUpdateUnreadCountDic:(NSDictionary *)unreadCountDic;
@end
未读数
获取未读数
针对单个 NIMRecentSession 的未读数,可以通过 NIMRecentSession
中 unreadCount
属性直接获取。
针对当前所有NIMRecentSession的总未读数,可以通过 NIMConversationManager
获取消息的总未读数。
@protocol NIMConversationManager <NSObject>
/**
* 获取所有未读数
* @discussion 只能在主线程调用
* @return 未读数
*/
- (NSInteger)allUnreadCount;
@end
也可以通过会话类型获取未读数,类型包括P2P,Team,SuperTeam。
@protocol NIMConversationManager <NSObject>
/**
* 按 SessionType 获取未读数
* @discussion 只能在主线程调用,包括忽略提醒的会话
* @param type 会话类型
* @return 未读数
*/
- (NSInteger)unreadCountOfType:(NIMSessionType)type;
@end
根据免打扰状态获取未读数
/**
* 获取所有需要通知/不需要通知的最近会话未读数
* @param notify 是否需要通知
* @return 未读数
* @discussion 群只有 notify state != NIMTeamNotifyStateNone 才算是不允许通知
*/
- (NSInteger)allUnreadCount:(BOOL)notify;
获取指定会话未读消息列表
- 异步接口:
@protocol NIMConversationManager <NSObject>
/**
* 获取指定会话所有未读消息列表,记了未读数的才算未读消息
*
* @param session 指定会话
* @param completion 未读消息列表
*/
- (void)allUnreadMessagesInSession: (NIMSession *)session completion:(NIMFetchMessageHistoryBlock)completion;
@end
- 同步接口:
/**
* 获取指定会话所有未读消息列表,记了未读数的才算未读消息
*
* @param session 指定会话
* @return 未读消息列表
*/
- (NSArray *)allUnreadMessagesInSession: (NIMSession *)session;
重置未读数
当 SDK 收到消息后,默认消息为未读消息,未读数累加 1 。因为 SDK 是和 UI 完全隔离的,SDK 无法自动感知何时消息已读,故需要上层开发者根据自己的 UI 逻辑,在恰当的时候,手动调用标记已读 接口来告诉 SDK ,从而 SDK 可以进行清除未读数,标记消息状态等之后的维护工作。 相应的最近会话(如果有的话)未读数会自动置 0 并且触发最近消息修改的回调。
请根据需要来对未读数清零,例如当前正在聊天的会话,不需要显示未读数,必须清零。非当前会话,只有当用户希望主动对某个会话或者全部会话进行清零的时候,才调用接口进行操作。
原型,分带回调和不带回调两个版本。
@protocol NIMConversationManager <NSObject>
/**
* 设置一个会话里所有消息置为已读。如果处于当前会话聊天界面,每次收到消息都需要调用该接口。
*
* @param session 需设置的会话
* @discussion 异步方法,消息会标记为设置的状态
*/
- (void)markAllMessagesReadInSession:(NIMSession *)session;
/**
* 设置一个会话里所有消息置为已读
*
* @param session 需设置的会话
* @param session 结果回调
* @discussion 异步方法,消息会标记为设置的状态
*/
- (void)markAllMessagesReadInSession:(NIMSession *)session completion:(NIMSendACKSessionsBlock)completion;
@end
示例
// NIMSessionViewController.m
- (void)onRecvMessages:(NSArray *)messages
{
....
//会话页直接监听收到消息后的回调,并由于当前页是在会话,直接认为已读
if ([session isEqual:self.session])
{
//只有当消息所属会话时会话页表示的会话时,才标记已读
[[NIMSDK sharedSDK].conversationManager markAllMessagesReadInSession:self.session];
}
....
}
此外,还支持批量设置会话的消息为已读,分带回调和不带回调两个版本。
@protocol NIMConversationManager <NSObject>
/**
* 批量设置多个会话消息已读
*
* @discussion 异步方法。不会触发单条 recentSession 更新的回调,但会触发回调 - onBatchMarkMessagesReadInSessions:
*/
- (void)batchMarkMessagesReadInSessions:(NSArray<NIMSession *> *)sessions;
/**
* 批量设置多个会话消息已读
*
* @param completion 结果回调。部分成功时,NIMBatchSendACKSessionsBlock的error参数标明错误原因,sessions参数标明出错的会话
* @discussion 异步方法。不会触发单条 recentSession 更新的回调,但会触发回调 - onBatchMarkMessagesReadInSessions:
*/
- (void)batchMarkMessagesReadInSessions:(NSArray<NIMSession *> *)sessions completion:(NIMBatchSendACKSessionsBlock)completion;
@end
此外,还支持设置所有最近会话的消息为已读。
@protocol NIMConversationManager <NSObject>
/**
* 设置所有会话消息为已读
*
* @param session 需设置的会话
* @discussion 异步方法,消息会标记为设置的状态。
*/
- (void)markAllMessagesRead;
@end
当然,也支持按照会话类型设置最近会话的消息为已读。
@protocol NIMConversationManager <NSObject>
/**
* 设置会话消息为已读
*
* @param type 会话类型
* @discussion 异步方法,消息会标记为设置的状态。不会触发单条 recentSession 更新的回调,但会触发回调 - (void)messagesReadOfType:
*/
- (void)markMessagesReadOfType:(NIMSessionType)type;
@end
未读数多端同步
开启会话的未读数多端同步后,在一个客户端读过的会话在其它端也会被标记为已读。
@interface NIMSDKConfig : NSObject
/**
* 是否需要多端同步未读数
*
* @param session 需设置的会话
* @discussion @discusssion 默认为 NO。设置成 YES 的情况下,同个账号多端(PC 和 移动端等)将同步未读计数。
*/
@property (nonatomic, assign) BOOL shouldSyncUnreadCount
@end
删除最近会话
删除最近会话
SDK 支持删除指定的本地最近会话。但会保留会话内的消息。调用时,总未读消息数会减去当前会话的未读数。
- API原型
@protocol NIMConversationManager <NSObject>
/**
* 删除某个最近会话,并标记为已读
*
* @param recentSession 待删除的最近会话
* @discussion 异步方法,删除最近会话,但保留会话内消息
*/
- (void)deleteRecentSession:(NIMRecentSession *)recentSession
/**
* 删除某个最近会话
*
* @param recentSession 待删除的最近会话
* @param option 是否删除漫游选项,isDeleteRoamMessage默认为NO
* @param completion 结果回调,不会回调代理方法didRemoveRecentSession:totalUnreadCount:
* @discussion 异步方法,删除最近会话,但保留会话内消息
*/
- (void)deleteRecentSession:(NIMRecentSession *)recentSession option:(NIMDeleteRecentSessionOption *)option completion:(NIMRemoveRemoteSessionBlock)completion;
@end
- NIMDeleteRecentSessionOption原型
注意:NIMDeleteRecentSessionOption#shouldMarkAllMessagesReadInSessions
的默认值为false,无配置项的接口使用的值不同
@interface NIMDeleteRecentSessionOption : NSObject
/**
* 是否移除该会话的服务端漫游消息
* @discussion ,默认为 NO,仅删除本地会话;为YES,将同时删除服务端漫游消息
*/
@property (nonatomic,assign) BOOL isDeleteRoamMessage;
/**
* 是否标记会话中所有消息已读
* @discussion ,默认为为 NO,仅删除本地会话;为YES,将同时标记会话中所有消息为已读
*/
@property (nonatomic,assign) BOOL shouldMarkAllMessagesReadInSessions;
@end
删除漫游消息
SDK 支持删除漫游消息,可以通过以下方法实现:
@protocol NIMConversationManager <NSObject>
/**
* 删除服务器端最近会话
*
* @param sessions 需要删除的会话列表,内部只能是NIMSession
* @param completion 完成的回调
* @discussion 调用这个接口成功后,当前会话之前的消息都不会漫游到其他端
*/
- (void)deleteRemoteSessions:(NSArray<NIMSession *> *)sessions
completion:(nullable NIMRemoveRemoteSessionBlock)completion;
@end
属性列表
参数 | 类型 | 说明 |
---|---|---|
sessions | NSArray<NIMSession *> * | 需要删除的会话列表,内部只能是NIMSession |
completion | NIMRemoveRemoteSessionBlock | 远端会话删除错误回调 |
若想同时删除服务端的历史消息,请参见删除单会话云端历史消息。