# 4\_3-带货场景-聊天室

* [1 功能概述](#_1-功能概述)
* [2 核心类介绍](#_2-核心类介绍)
  * [2.1 PLVECChatroomViewModel](#_21-plvecchatroomviewmodel)
    * [2.1.1 生命周期](#_211-生命周期)
    * [2.1.2 获取聊天记录](#_212-获取聊天记录)
    * [2.1.3 发送消息](#_213-发送消息)
    * [2.1.4 消息数组](#_214-消息数组)
    * [2.1.5 监听与回调](#_215-监听与回调)

#### 1 功能概述

聊天室模块包括发言、点赞、历史记录、欢迎语等功能。聊天室模块在UI、交互、功能上，相较于其他模块，都会更复杂更庞大。因此设计、搭建、维护一个聊天室，也是一件较为费时费力的事情。我们推荐直接使用保利威封装好的聊天室模块，该部分代码完全开源，支持直接使用，以及二次开发。

#### 2 核心类介绍

**2.1 PLVECChatroomViewModel**

`PLVECChatroomViewModel` 是带货场景 Scene 层聊天室的核心类，由于一个应用只允许存在一个聊天室，所以 `PLVECChatroomViewModel` 采用的是单例的模式，负责创建、持有、销毁 Common 层聊天室核心类 `PLVChatroomPresenter` 的实例对象以及与 Common 层聊天室模块进行通信，核心类 `PLVECChatroomViewModel` 提供功能如下：

1. 对 View 层提供发送消息的接口；
2. 管理 Common 层返回的消息模型；
3. 在 View 层需要刷新 UI、更新列表数据时，通过回调通知 View 层。

**2.1.1 生命周期**

`PLVECChatroomViewModel` 是单例类，进入直播间启动聊天室的时候调用 -`setup` 方法，离开直播间时调用 -`clear` 方法，代码如下：

```objective-c
// 使用新的直播间数据启动聊天室管理器
[[PLVECChatroomViewModel sharedViewModel] setup];
// 退出前调用，用于资源释放、状态位清零
[[PLVECChatroomViewModel sharedViewModel] clear];
```

代码注释提到的“直播间数据”指的是 `PLVRoomDataManager` 单例持有的 `roomData`。

**2.1.2 获取聊天记录**

Common 层聊天室核心类 `PLVChatroomPresenter` 在初始化完毕之后，会自动获取第一页的聊天记录，获取更多聊天记录代码如下：

```objective-c
[[PLVECChatroomViewModel sharedViewModel] loadHistory];
```

`-loadHistory` 使用在 2.1.1 的 `-setup` 方法里初始化的 presenter 对象，调用 Common 层聊天室模块获取聊天室记录。

**2.1.3 发送消息**

`PLVECChatroomViewModel` 类提供带货场景所需的发送消息的API，具体接口定义如下：

```objective-c
/// 发送文本消息
/// @param content 消息文本
/// @return YES表示数据将有更新，可等待收到回调后刷新列表；NO表示socket未登录或房间关闭，可进行toast提示
- (BOOL)sendSpeakMessage:(NSString *)content;

/// 发送礼物消息
/// @param data 礼物消息data字段
/// @param tip 礼物消息tip字段
/// @return 是否成功发送的布尔值
- (BOOL)sendGiftMessageWithData:(NSDictionary *)data tip:(NSString *)tip;

/// 发送自定义消息
/// @param event 自定义消息event字段
/// @param data 自定义消息data字段
/// @param tip 自定义消息tip字段
/// @param emitMode 自定义消息emitMode字段
/// @return 是否成功发送的布尔值
- (BOOL)sendCustomMessageWithEvent:(NSString *)event
                              data:(NSDictionary *)data
                               tip:(NSString * _Nullable)tip
                          emitMode:(int)emitMode;

/// 发送点赞消息
/// 点赞数的实时更新通过监听roomData的likeCount获得
- (void)sendLike;
```

**2.1.4 消息数组**

`PLVECChatroomViewModel` 类提供以下消息列表数组，作为聊天室 View 层的数据源：

```objective-c
/// 全部消息数组
@property (nonatomic, strong, readonly) NSMutableArray <PLVChatModel *> *chatArray;
```

**2.1.5 监听与回调**

`PLVECChatroomViewModel` 提供了属性 `delegate` 用于设置回调监听，属性 `delegate` 遵循协议 `PLVECChatroomViewModelProtocol`，用于在 View 层需要刷新 UI、更新列表数据时，通过回调通知 View 层：

```objective-c
@protocol PLVECChatroomViewModelProtocol <NSObject>

@optional

/// 返回本地发送的公聊消息（包含禁言的情况）
/// 用于刷新列表、滚动列表到底部
- (void)chatroomManager_didSendMessage;

/// 返回socket接收到的公聊消息
/// 用于刷新列表、显示新消息提示
- (void)chatroomManager_didReceiveMessages;

/// socket通知有消息被删除（1条或多条）
/// 用于刷新列表
- (void)chatroomManager_didMessageDeleted;

/// 获取历史聊天记录成功时触发
/// 用于刷新列表，停止【下拉加载更多】控件的动画
/// @param noMore 是否还有更多历史消息，YES表示已加载完，此时可隐藏【下拉加载更多】控件
/// @param first  是否是初次加载历史消息，初次加载需滚动列表到底部
- (void)chatroomManager_loadHistorySuccess:(BOOL)noMore firstTime:(BOOL)first;

/// 获取历史聊天消息失败时触发
/// 用于停止【下拉加载更多】控件的动画
- (void)chatroomManager_loadHistoryFailure;

/// 当前时间段内如果有用户登录聊天室（包括自己），间隔2秒触发一次
/// @param userArray 登录聊天室的用户数组，如果为nil，表示当前时间段内当前用户有登录事件
- (void)chatroomManager_loginUsers:(NSArray <PLVChatUser *> * _Nullable )userArray;

@end
```

