引用回复
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 全局配置开启带引用关系信息的消息。
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 内置会话页面暂不将自定义消息加入默认回复类型白名单;如果业务需要发送自定义消息作为回复消息,可将自定义消息类型加入白名单。
RCKitConfigCenter.message.quoteMessageTypeWhiteList = @[
[RCTextMessage getObjectName],
[RCImageMessage getObjectName],
[RCFileMessage getObjectName]
];
引用语音回复的转文字
开启带引用关系信息的消息后,如果回复消息是普通语音消息或高清语音消息,且应用已开通并启用 IMKit 语音转文字能力,IMKit 会按语音消息原有规则展示转文字结果。转换后的文字是否展示,由消息中 RCSpeechToTextInfo 的 isVisible 状态控制。
定制化
自定义引用消息的 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:。
- (BOOL)shouldShowReferenceMenuItemForMessageModel:(RCMessageModel *)messageModel {
if ([messageModel.content isKindOfClass:[RCDOrderMessage class]]) {
return YES;
}
return [super shouldShowReferenceMenuItemForMessageModel:messageModel];
}
注册自定义引用卡片 View
自定义引用卡片 View 需要继承 RCMessageCellReferenceContentView。建议在会话页面子类的 registerCustomCellsAndMessages 方法中调用 registerMessageCellReferenceContentViewClass:forMessageClass: 注册。
- (void)registerCustomCellsAndMessages {
[super registerCustomCellsAndMessages];
[self registerClass:[RCDOrderMessageCell class]
forMessageClass:[RCDOrderMessage class]];
[self registerMessageCellReferenceContentViewClass:[RCDOrderReferenceContentView class]
forMessageClass:[RCDOrderMessage class]];
}
自定义 View 需要返回引用卡片尺寸,并在绑定数据时渲染被引用消息内容。maxWidth 表示当前引用卡片可用的最大宽度,返回的宽度不应超过该值。
@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: 方法中处理。
// 在 RCDOrderReferenceContentView 内触发事件。
[self performAction:@"openOrder"
extra:@{@"orderId": orderMessage.orderId ?: @""}];
// 在 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 会继续使用默认引用区域。
- (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: 中绑定被引用消息数据。
@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。
关闭引用回复功能
您可以通过全局配置关闭引用回复功能。
RCKitConfigCenter.message.enableMessageReference = NO;