# 高级功能

# 自定义消息

七鱼 iOS SDK 的 自定义消息 功能主要用于在聊天列表中任意追加插入更新删除自定义消息,支持自定义消息数据存储及更新,支持注入自定义视图并修改布局配置,以 Message — Model — View 形式形成消息到视图的对应关系,开发原则为数据驱动视图,所有视图的更新都依赖于数据的更新。

功能对外接口位于 QIYU_iOS_SDK/ExportHeaders/Custom 中,相关类库说明请参考 接入说明-类库说明 章节,这里不再赘述。

# 用法说明

自定义消息模块针对QYSessionViewController扩展了分类QYCustomSessionViewController,主要用于扩展自定义消息相关接口,避免放在原来的头文件中太过混乱。提供以下接口:

# 注册映射关系(必须)

/**
 *  注册message-model-contentView的映射关系(必须)
 *  @discussion 若要使用自定义消息,必须调用此方法设置映射关系!
 *  @param messageClass     消息类
 *  @param modelClass       消息对应的数据模型类
 *  @param contentViewClass 消息对应的视图
 */
- (void)registerCustomMessageClass:(Class)messageClass
                        modelClass:(Class)modelClass
                  contentViewClass:(Class)contentViewClass;

需要在创建QYSessionViewController对象时调用该接口注册 自定义消息 Message-自定义数据源 Model-自定义视图 ContentView 的映射关系,这样 SDK 才能在遇到自定义 Message 时取出其对应的 Model 和 ContentView 类去创建相应的对象。

# 设置/移除消息事件代理

/**
 *  设置消息事件委托对象
 *  @param delegate 被委托对象
 */
- (void)addCustomMessageDelegate:(id<QYCustomMessageDelegate>)delegate;

/**
 *  清除消息事件委托对象
 *  @param delegate 被清除的委托对象
 */
- (void)removeCustomMessageDelegate:(id<QYCustomMessageDelegate>)delegate;

可将任意对象设置为消息事件代理,用来接收消息在追加、插入、更新、删除等操作时抛出的某些事件,目前有如下几类时机抛出:

@protocol QYCustomMessageDelegate <NSObject>

@optional
/**
 *  追加消息的回调,此时消息已持久化(若需),还未刷新界面
 */
- (void)onAddMessageBeforeReload:(QYCustomMessage *)message;

/**
 *  插入消息的回调,此时消息已持久化(若需),还未刷新界面
 */
- (void)onInsertMessageBeforeReload:(QYCustomMessage *)message;

/**
 *  更新消息的回调,此时消息已持久化(若需),还未刷新界面
 */
- (void)onUpdateMessageBeforeReload:(QYCustomMessage *)message;

/**
 *  删除消息的回调,此时消息已持久化(若需),还未刷新界面
 */
- (void)onDeleteMessageBeforeReload:(QYCustomMessage *)message;

@end

# 设置/移除视图事件代理

/**
 *  设置消息视图委托对象
 *  @param delegate 被委托对象
 */
- (void)addCustomContentViewDelegate:(id<QYCustomContentViewDelegate>)delegate;

/**
 *  清除消息视图委托对象
 *  @param delegate 被清除的委托对象
 */
- (void)removeCustomContentViewDelegate:(id<QYCustomContentViewDelegate>)delegate;

可将任意对象设置为消息视图事件代理,用来接收并处理点击头像事件、长按 cell 事件、contentView 上自定义控件抛出的各类事件:

@protocol QYCustomContentViewDelegate <NSObject>

@optional
/**
 *  自定义事件,通过QYCustomContentView的delegate去调用onCatchEvent:事件
 *  若事件涉及到更新消息及视图则尽量使用onCatchEvent:抛出,若未涉及消息及视图更新,可直接响应事件,无需使用该方法抛出
 */
- (void)onCatchEvent:(QYCustomEvent *)event;

/**
 *  头像点击事件
 */
- (void)onTapAvatar:(QYCustomEvent *)event;

/**
 *  消息体长按事件
 */
- (void)onLongPressCell:(QYCustomEvent *)event;

@end

# 追加自定义消息

/**
 *  从尾部追加消息
 *  @param message    消息对象
 *  @param save       是否需要持久化消息数据
 *  @param reload     是否需要刷新界面
 *  @param completion 消息持久化结果回调
 */
- (void)addCustomMessage:(QYCustomMessage *)message
            needSaveData:(BOOL)save
          needReloadView:(BOOL)reload
              completion:(QYCustomMessageCompletion)completion;

通过此接口追加一条自定义消息,传入QYCustomMessage或其子类对象,并告知是否需要将数据持久化至数据库、是否需要立即刷新界面,该接口会给出结果回调,并抛出部分错误信息:

/**
 *  错误码
 */
typedef NS_ENUM(NSInteger, QYCustomMessageErrorCode) {
    QYCustomMessageErrorCodeUnknown         = 0,    //未知错误
    QYCustomMessageErrorCodeInvalidParam    = 1,    //错误参数
    QYCustomMessageErrorCodeInvalidMessage  = 2,    //无效消息体
    QYCustomMessageErrorCodeSQLFailed       = 3,    //SQL语句执行失败
};

/**
 *  消息持久化结果block
 *  @param error 错误信息
 */
typedef void(^QYCustomMessageCompletion)(NSError *error);

调用此接口时会自动调用QYCustomMessageCoding协议中的序列化/反序列化方法去 encode/decode 数据,自动调用QYCustomModelLayoutDataSource协议中的各个布局相关方法获得布局参数,最终自动调用initCustomContentView创建自定义视图,并通过refreshData:方法刷新视图。

# 插入消息

/**
 *  从头部插入消息
 *  @discussion 插入消息不支持持久化数据
 *  @param message  消息对象
 */
- (void)insertCustomMessage:(QYCustomMessage *)message;

/**
 *  从中间插入消息
 *  @discussion 插入消息不支持持久化数据
 *  @param message  消息对象
 *  @param index    插入位置
 */
- (void)insertCustomMessage:(QYCustomMessage *)message index:(NSInteger)index;

在消息列表的某个位置插入一条消息,需注意,因底层设计原因,目前不支持插入消息的数据持久化,故插入消息接口只能实现在 table 的数据源 DataSource 中临时插入消息并刷新界面,退出聊天界面再次进入后消息消失。

# 更新消息

/**
 *  刷新消息
 *  @param message  消息对象
 *  @param save     是否需要持久化消息数据
 *  @param reload   是否需要刷新界面
 *  @param completion 消息持久化结果回调
 */
- (void)updateCustomMessage:(QYCustomMessage *)message
               needSaveData:(BOOL)save
             needReloadView:(BOOL)reload
                 completion:(QYCustomMessageCompletion)completion;

更新数据库 Database 或是数据源 DataSource 中的某条消息,一般在调用该接口前,会先从数据库/数据源中取出该条消息(利用消息ID取出),更新部分消息属性,然后再调用接口更新,同样会自动触发 Model 和 ContentView 的部分方法,并给出回调结果。

# 删除消息

/**
 *  删除消息
 *  @param message  消息对象
 *  @param save     删除记录是否同步至数据库
 *  @param reload   是否需要刷新界面
 */
- (void)deleteCustomMessage:(QYCustomMessage *)message
               needSaveData:(BOOL)save
             needReloadView:(BOOL)reload;

删除数据库 Database 或是数据源 DataSource 中的某条消息。

# 获取消息

/**
 *  从数据库中取出消息
 *  @param messageId 消息的唯一ID
 *  @return 取出的消息体
 */
- (QYCustomMessage *)fetchCustomMessageFromDatabaseForMessageId:(NSString *)messageId;

/**
 *  从当前table的dataSource中取出消息
 *  @param messageId 消息的唯一ID
 *  @return 取出的消息体
 */
- (QYCustomMessage *)fetchCustomMessageFromDataSourceForMessageId:(NSString *)messageId;

从数据库 Database 或是数据源 DataSource 中获取某条消息,获取消息传入的唯一参数为消息ID,消息ID的生成必须是自定义消息创建后,通过调用 “ 追加add/插入insert ” 接口后才可同步获取。

# 用法示例

使用自定义消息功能可在任意时刻向消息流中追加自定义的文本、图片、卡片等任意类型消息,可配合拦截请求客服事件实现定制欢迎消息功能,如开发者有需求,具体用法示例可咨询相关技术支持。