跳到主要内容

引用回复

IMKit 支持引用回复功能,允许用户在聊天页面中引用并回复一条消息。默认情况下,IMKit 使用 RCReferenceMessage(类型标识:RC:ReferenceMsg)发送回复内容。

提示
  • 从 5.38.0 版本开始,IMKit 支持带引用关系信息的消息。
  • 该功能需要在 IMKit SDK 中配置开启后才能使用;未开启时,IMKit 仍使用原引用消息逻辑。

使用限制

旧版引用回复功能有以下限制:

  • 仅支持文本消息、文件消息、图文消息、图片消息、引用消息的引用。
  • 引用深度仅支持一层,即只能引用回复原始消息。如果出现多重引用,只展示上一层被引用消息内容。
  • 被引用消息撤回后,引用消息仍会展示被引用的消息内容。

带引用关系信息的消息有以下限制:

  • 引用展示仅支持一层。如果被引用消息本身携带引用关系,引用卡片只展示当前被引用消息对应的一层内容,不会递归展示更早的引用层级。
  • IMKit 内置会话页面支持引用已发送成功且有 messageUId 的消息。用户发送回复时,默认支持文本、图片、GIF、小视频、普通语音、高清语音、文件、位置消息作为回复内容。您可以通过 quoteMessageTypeWhiteList 调整允许发送的回复消息类型。
  • 开启后,低版本 SDK 会按原消息类型展示回复消息,无法展示引用关系信息。

用法

IMKit 会话页面默认已启用引用回复功能。用户在会话页面长按消息,并在弹出的消息菜单中选择引用消息,即可引用该消息。在输入区添加回复内容后,SDK 默认会将回复内容与被引用消息组合为 RCReferenceMessage,并发送到会话中。

带引用关系信息的消息

默认的引用回复会将输入内容与被引用消息组合为 RCReferenceMessage 发送。开启带引用关系信息的消息后,SDK 会在实际发送的消息对象上写入引用关系信息 RCQuoteInfo,并通过 RCMessage.quoteInfo 标识该消息回复的是哪一条原始消息。原 RC:ReferenceMsg 仍然可以正常使用。

带引用关系信息的消息默认关闭。开启后,用户引用一条消息后,可以发送文本、图片、GIF、小视频、普通语音、高清语音、文件、位置等多种类型的消息作为回复。

您可以通过 IMKit 全局配置开启带引用关系信息的消息。

Objective C
RCKitConfigCenter.message.enableQuoteV2 = YES;

发送前,请确认被引用消息已存在于本地消息库,且 messageUId 有效。SDK 发送时会根据 quoteInfo.messageUId 查询被引用消息;如果未查询到对应消息,发送会失败并返回 RC_DB_DATA_NOT_FOUND(错误码:34304)。

可发送的回复消息类型由 quoteMessageTypeWhiteList 控制。默认包含:

消息类型类型标识
文本消息RC:TxtMsg
图片消息RC:ImgMsg
GIF 消息RC:GIFMsg
小视频消息RC:SightMsg
普通语音消息RC:VcMsg
高清语音消息RC:HQVCMsg
文件消息RC:FileMsg
位置消息RC:LBSMsg

如需限制可作为回复发送的消息类型,可以重新设置白名单。IMKit 内置会话页面暂不将自定义消息加入默认回复类型白名单;如果业务需要发送自定义消息作为回复消息,可将自定义消息类型加入白名单。

Objective C
RCKitConfigCenter.message.quoteMessageTypeWhiteList = @[
[RCTextMessage getObjectName],
[RCImageMessage getObjectName],
[RCFileMessage getObjectName]
];

引用语音回复的转文字

开启带引用关系信息的消息后,如果回复消息是普通语音消息或高清语音消息,且应用已开通并启用 IMKit 语音转文字能力,IMKit 会按语音消息原有规则展示转文字结果。转换后的文字是否展示,由消息中 RCSpeechToTextInfoisVisible 状态控制。

定制化

自定义引用消息的 UI

默认引用回复使用 RCReferenceMessageCell 模板展示引用消息(RC:ReferenceMsg)。开启带引用关系信息的消息后,回复消息仍使用实际消息类型对应的 Cell 展示,引用关系保存在 RCMessage.quoteInfo 中,IMKit 内置消息 Cell 会根据 quoteInfo 展示引用卡片。引用回复的点击行为与实际消息类型的点击行为保持一致。

IMKit 中所有消息模板都继承自 RCMessageCell,自定义消息 Cell 也需要继承 RCMessageCell。如需自定义引用消息整体 UI,例如自定义旧版引用消息(RC:ReferenceMsg)展示样式,或自定义带引用关系信息消息的整体 Cell,请按自定义消息 Cell 方式处理。详见修改消息的展示样式

自定义引用卡片展示

如果只需要自定义带引用关系信息消息中的引用卡片展示,可以为被引用的自定义消息注册消息 Cell 内的引用卡片 View。注册后,当某条回复消息引用该自定义消息时,IMKit 会在回复消息 Cell 的引用卡片区域使用自定义 View 展示被引用消息内容。

显示自定义消息的引用入口

IMKit 默认支持文本、图片、文件、图文和旧版引用消息显示引用消息入口。如果需要让自定义消息也显示该入口,可以在 RCConversationViewController 子类中重写 shouldShowReferenceMenuItemForMessageModel:

Objective C
- (BOOL)shouldShowReferenceMenuItemForMessageModel:(RCMessageModel *)messageModel {
if ([messageModel.content isKindOfClass:[RCDOrderMessage class]]) {
return YES;
}
return [super shouldShowReferenceMenuItemForMessageModel:messageModel];
}

注册自定义引用卡片 View

自定义引用卡片 View 需要继承 RCMessageCellReferenceContentView。建议在会话页面子类的 registerCustomCellsAndMessages 方法中调用 registerMessageCellReferenceContentViewClass:forMessageClass: 注册。

Objective C
- (void)registerCustomCellsAndMessages {
[super registerCustomCellsAndMessages];

[self registerClass:[RCDOrderMessageCell class]
forMessageClass:[RCDOrderMessage class]];

[self registerMessageCellReferenceContentViewClass:[RCDOrderReferenceContentView class]
forMessageClass:[RCDOrderMessage class]];
}

自定义 View 需要返回引用卡片尺寸,并在绑定数据时渲染被引用消息内容。maxWidth 表示当前引用卡片可用的最大宽度,返回的宽度不应超过该值。

Objective C
@interface RCDOrderReferenceContentView : RCMessageCellReferenceContentView
@end

@implementation RCDOrderReferenceContentView

+ (CGSize)sizeForReferencedContent:(RCMessageContent *)referencedContent
messageModel:(RCMessageModel *)messageModel
maxWidth:(CGFloat)maxWidth {
return CGSizeMake(MIN(maxWidth, 220), 48);
}

- (void)setReferencedContent:(RCMessageContent *)referencedContent
messageModel:(RCMessageModel *)messageModel {
[super setReferencedContent:referencedContent messageModel:messageModel];
if (![referencedContent isKindOfClass:[RCDOrderMessage class]]) {
return;
}

RCDOrderMessage *orderMessage = (RCDOrderMessage *)referencedContent;
// 根据 orderMessage 渲染引用卡片内容。
}

@end

处理引用卡片内的自定义事件

如果自定义引用卡片 View 内部需要触发业务事件,可以调用 performAction:extra:。IMKit 会将事件转发到会话页面的 messageCellReferenceContentView:didPerformAction:extra: 方法中处理。

Objective C
// 在 RCDOrderReferenceContentView 内触发事件。
[self performAction:@"openOrder"
extra:@{@"orderId": orderMessage.orderId ?: @""}];
Objective C
// 在 RCConversationViewController 子类中处理事件。
- (void)messageCellReferenceContentView:(RCMessageCellReferenceContentView *)referenceContentView
didPerformAction:(NSString *)action
extra:(NSDictionary *)extra {
if ([action isEqualToString:@"openOrder"]) {
NSString *orderId = extra[@"orderId"];
// 根据 orderId 跳转订单详情。
}
}
提示
  • 未注册自定义引用卡片 View 时,IMKit 会继续使用默认引用卡片样式。
  • 该能力只处理消息列表中回复消息 Cell 内的引用卡片展示,不控制输入框上方的引用区域。
  • 如果需要自定义输入框上方的引用区域,请重写 referenceInputBarViewForMessageModel:,并返回继承自 RCReferenceInputBarView 的自定义 View。

自定义输入框上方引用区域

用户在会话页面选择引用消息后,IMKit 默认会在输入框上方展示引用区域。如果需要自定义该区域的展示,例如为自定义消息展示专属摘要、头像或操作按钮,可以在 RCConversationViewController 子类中重写 referenceInputBarViewForMessageModel:,并返回继承自 RCReferenceInputBarView 的自定义 View。返回 nil 时,IMKit 会继续使用默认引用区域。

Objective C
- (RCReferenceInputBarView *)referenceInputBarViewForMessageModel:(RCMessageModel *)messageModel {
if (![messageModel.content isKindOfClass:[RCDOrderMessage class]]) {
return nil;
}

RCDOrderInputReferenceView *view =
[[RCDOrderInputReferenceView alloc] initWithFrame:CGRectMake(0, 0, 0, 60)];

__weak typeof(self) weakSelf = self;
view.cancelHandler = ^{
[weakSelf cancelReference];
};
return view;
}

自定义输入框引用区域 View 需要继承 RCReferenceInputBarView,并在 setReferencedMessageModel: 中绑定被引用消息数据。

Objective C
@interface RCDOrderInputReferenceView : RCReferenceInputBarView

@property (nonatomic, copy) void (^cancelHandler)(void);

@end

@implementation RCDOrderInputReferenceView

- (void)setReferencedMessageModel:(RCMessageModel *)messageModel {
[super setReferencedMessageModel:messageModel];
if (![messageModel.content isKindOfClass:[RCDOrderMessage class]]) {
return;
}

RCDOrderMessage *orderMessage = (RCDOrderMessage *)messageModel.content;
// 根据 orderMessage 渲染输入框上方引用区域。
}

- (CGSize)sizeThatFits:(CGSize)size {
return CGSizeMake(size.width, 60);
}

- (void)cancelButtonClicked {
if (self.cancelHandler) {
self.cancelHandler();
}
}

@end
提示
  • IMKit 会负责添加、布局、绑定引用消息模型以及移除自定义 View。
  • 自定义 View 的宽度由 IMKit 在布局时统一设置;高度可以通过初始化时设置 frame 高度,或重写 sizeThatFits: 返回。
  • 取消按钮、整块点击手势以及 View 内部交互需要业务自行实现。需要取消当前引用时,可在业务回调中调用会话页面的 cancelReference

关闭引用回复功能

您可以通过全局配置关闭引用回复功能。

Objective C
RCKitConfigCenter.message.enableMessageReference = NO;