会话
<p>[TOC]</p>
<h2>最近会话概念</h2>
<p>最近会话用于表示会话列表页的数据模型。当用户发送,收取及删除消息时,都会同时去修改最近会话。</p>
<p>当收到或者一条消息时,会自动生成这个消息对应的最近会话。但值得注意的是最近会话和会话并不是一一对应的关系,删除最近会话并不会影响会话。</p>
<h2>最近会话类与属性</h2>
<p>最近会话在 SDK 中用 QDRecentSession 表示</p>
<pre><code>@interface QDRecentSession : NSObject
/**
* 当前会话
*/
@property (nonatomic, readonly, strong) QDSession *session;
/**
* 未读消息数
*/
@property (nonatomic, readonly, assign) NSInteger unreadCount;
/**
* 最后一条消息
*/
@property (nonatomic, readonly, strong, nullable) QDMessage *lastMessage;
/**
* 本地扩展
*/
@property (nonatomic, readonly, copy , nullable) NSDictionary *localExt;
@end</code></pre>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">session</td>
<td style="text-align: center;">QDSession</td>
<td style="text-align: center;">表示当前会话</td>
</tr>
<tr>
<td style="text-align: center;">lastMessage</td>
<td style="text-align: center;">QDMessage</td>
<td style="text-align: center;">当前会话的最后一条消息</td>
</tr>
<tr>
<td style="text-align: center;">unreadCount</td>
<td style="text-align: center;">NSInteger</td>
<td style="text-align: center;">未读消息数,为保证线程安全,请在主线程中获取</td>
</tr>
<tr>
<td style="text-align: center;">localExt</td>
<td style="text-align: center;">NSDictionary</td>
<td style="text-align: center;">最近会话的本地扩展,修改后,需要调用 QDIMChatManager 中 updateRecentLocalExt:recentSession: 方法,才可以存储到本地</td>
</tr>
</tbody>
</table>
<ul>
<li>获取最近会话,一般用于首页显示会话列表</li>
</ul>
<p>原型</p>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
* 获取所有最近会话
* @return 最近会话列表
*/
- (nullable NSArray<QDRecentSession *> *)allRecentSessions;
@end</code></pre>
<ul>
<li>最近会话的通知</li>
</ul>
<p><code>QDConversationManagerDelegate</code> 提供了最近会话的三个回调通知上层:</p>
<p>分别为增加,修改,删除最近会话的回调:</p>
<pre><code>@protocol QDConversationManagerDelegate <NSObject>
/**
* 增加最近会话的回调
*
* @param recentSession 最近会话
* @param totalUnreadCount 目前总未读数
* @discussion 当新增一条消息,并且本地不存在该消息所属的会话时,会触发此回调。
*/
- (void)didAddRecentSession:(QDRecentSession *)recentSession totalUnreadCount:(NSInteger)totalUnreadCount;
/**
* 最近会话修改的回调
*
* @param recentSession 最近会话
* @param totalUnreadCount 目前总未读数
* @discussion 触发条件包括: 1.当新增一条消息,并且本地存在该消息所属的会话。
* 2.所属会话的未读清零。
* 3.所属会话的最后一条消息的内容发送变化。(例如成功发送后,修正发送时间为服务器时间)
* 4.删除消息,并且删除的消息为当前会话的最后一条消息。
*/
- (void)didUpdateRecentSession:(QDRecentSession *)recentSession totalUnreadCount:(NSInteger)totalUnreadCount;
/**
* 删除最近会话的回调
*
* @param recentSession 最近会话
* @param totalUnreadCount 目前总未读数
*/
- (void)didRemoveRecentSession:(QDRecentSession *)recentSession totalUnreadCount:(NSInteger)totalUnreadCount;
@end</code></pre>
<p>属性列表<br />
| 参数 | 类型 | 说明 |<br />
| :---: | :---: | :---: |<br />
| recentSession | QDRecentSession | 产生变化的最近会话 |<br />
| totalUnreadCount | NSInteger | 目前总未读数 |</p>
<p>获取单个 QDRecentSession 的未读数时,可以通过回调上来的 QDRecentSession 中 unreadCount 属性直接获取。</p>
<ul>
<li>最近消息添加</li>
</ul>
<p>开发者无法自己添加最近消息,最近消息会在发送或者收到消息的时候自动添加,并触发增加最近会话的回调。</p>
<ul>
<li>总未读数获取</li>
</ul>
<p>可以通过 QDChatManager 获取消息的总未读数,注意为了保证线程安全,只能在主线程上调用读取此数据</p>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
* 获取所有未读数
* @discussion 包括忽略提醒的会话
* @return 未读数
*/
- (NSInteger)allUnreadCount;
@end</code></pre>
<ul>
<li>标记消息已读
当 SDK 收到消息后,默认消息为未读消息,未读数累加 1 。因为 SDK 是和 UI 完全隔离的,SDK 无法自动感知何时消息已读,故需要上层开发者根据自己的 UI 逻辑,在恰当的时候,手动调用标记已读 接口来告诉 SDK ,从而 SDK 可以进行清除未读数,标记消息状态等之后的维护工作。 相应的最近会话(如果有的话)未读数会自动置 0 并且触发最近消息修改的回调。</li>
</ul>
<p>原型</p>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
设置一个会话里所有消息置为已读
@param session 需设置的会话
*/
- (void)markAllMessagesReadInSession:(QDSession *)session;
@end</code></pre>
<p>示例</p>
<pre><code>- (void)onRecvMessages:(NSArray *)messages
{
....
//会话页直接监听收到消息后的回调,并由于当前页是在会话,直接认为已读
if ([session isEqual:self.session])
{
//只有当消息所属会话时会话页表示的会话时,才标记已读
[[QDClient sharedClient].chatManager markAllMessagesReadInSession:self.session];
}
....
}</code></pre>
<ul>
<li>消息/会话的删除</li>
</ul>
<p>单条消息的删除</p>
<pre><code>/**
* 删除某条消息
*
* @param message 待删除的聊天消息
*/
- (void)deleteMessage:(NIMMessage *)message;</code></pre>
<p>调用此方法时,如果删除的是最后一条消息,消息所属的最近会话的 lastMessage 属性会自动变成上一条消息(没有则为空消息),同时触发最近消息修改的回调。</p>
<p>单个会话批量消息删除</p>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
* 删除某个会话的所有消息
*
* @param session 待删除会话
*/
- (void)deleteAllmessagesInSession:(QDSession *)session;
@end</code></pre>
<ul>
<li>增加最近空白会话</li>
</ul>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
增加某个最近会话
@param session 待增加的最近会话
*/
- (void)addEmptyRecentSessionBySession:(QDSession *)session;
@end</code></pre>
<ul>
<li>最近会话的删除</li>
</ul>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
删除某个最近会话
@param recentSession 待删除的最近会话
*/
- (void)deleteRecentSession:(QDRecentSession *)recentSession;
@end</code></pre>
<p>只会删除最近会话,但保留会话内消息。调用时,总未读消息数会减去当前会话的未读数。调用此方法触发最近消息删除的回调。</p>
<ul>
<li>清空所有会话的消息</li>
</ul>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
* 删除所有消息
*/
- (void)deleteAllMessages;
@end</code></pre>
<ul>
<li>写入本地消息
部分类型消息支持不发送直接写入本地,目前支持的类型为: 1.文本类型 ( QDMessageTypeText ) 2.自定义类型 ( QDMessageTypeCustom ) </li>
</ul>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
写入消息
@param message 需要更新的消息
@param session 需要更新的会话
@param completion 完成后的回调
@discussion 当保存消息成功之后,会收到 onRecvMessages: 回调。不允许插入已存在的消息
*/
- (void)saveMessage:(QDMessage *)message forSession:(QDSession *)session completion:(void(^ _Nullable)(NSError * __nullable error))completion;
@end</code></pre>
<ul>
<li>最近会话的本地扩展</li>
</ul>
<p>最近会话提供本地扩展能力,可以用来开发 @ 以及 置顶 等功能。</p>
<p>开发者可以通过 RecentSession 的 localExt 接口读取扩展。</p>
<p>并通过调用 QDIMChatManager 修改本地扩展信息</p>
<pre><code>@protocol QDIMChatManager <NSObject>
/**
更新最近会话的本地扩展
@param ext 扩展信息
@param recentSession 需要更新的最近会话
@discussion 此扩展不会漫游到其他端,上层需要保证 NSDictionary 可以转换为 JSON。
*/
- (void)updateRecentLocalExt:(nullable NSDictionary *)ext recentSession:(QDRecentSession *)recentSession;
@end</code></pre>
<p>属性列表</p>
<table>
<thead>
<tr>
<th style="text-align: center;">参数</th>
<th style="text-align: center;">类型</th>
<th style="text-align: center;">说明</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align: center;">ext</td>
<td style="text-align: center;">NSDictionary</td>
<td style="text-align: center;">扩展信息,上层需要保证能将 NSDictionary 转换为 JSON</td>
</tr>
<tr>
<td style="text-align: center;">recentSession</td>
<td style="text-align: center;">QDRecentSession</td>
<td style="text-align: center;">要更新的最近会话</td>
</tr>
</tbody>
</table>
<p>示例</p>
<pre><code>+ (void)addRecentSessionMark:(QDSession *)session type:(QiRecentSessionMarkType)type
{
QDRecentSession *recent = [[QDClient sharedClient].chatManager recentSessionBySession:session];
if (recent)
{
NSDictionary *localExt = recent.localExt?:@{};
NSMutableDictionary *dict = [localExt mutableCopy];
NSString *key = [QiSessionUtil keyForMarkType:type];
[dict setObject:@(YES) forKey:key];
[[QDClient sharedClient].chatManager updateRecentLocalExt:dict recentSession:recent];
}
}</code></pre>