实现自定义消息收发
更新时间: 2024/09/27 10:50:00
前言
云信 SDK 内置了包括图片,音频,视频等多媒体消息,但用户基于自己的应用场景往往需要某些特殊的消息类型,因此需要自定义消息类型。
本文主要介绍如何从 model 到 UI,一步步实现自定义消息类型。
IM UIKit 的会话消息模块(NEChatUIKit
)默认实现了文本消息、图片消息等基本消息类型的发送和展示。如果这些消息类型无法满足您的业务需求,您可新增自定义消息类型。
基本消息类型
消息类型 |
显示效果 |
是否需要额外集成 |
---|---|---|
文本消息 | 否,集成会话界面即可用 | |
图片消息 | 否,集成会话界面即可用 | |
语音消息 | 否,集成会话界面即可用 | |
视频消息 | 否,集成会话界面即可用 | |
表情 | 否,集成会话界面即可用 | |
文件消息 | 否,集成会话界面即可用具体配置操作如下请在 Xcode 中选择TARGETS -> Signing&Capabilities -> iCloud,然后勾选 iCloud Documents。 |
|
地理位置 | 是,见实现地理位置消息功能 |
前提条件
已集成会话消息界面。
实现流程
步骤 1:创建自定义消息
在云信 SDK 中,需要通过 NIMCustomObject
来实现自定义消息类型,内部包含一个实现 NIMCustomAttachment
协议的对象。UIKit 已经提供了一个实现 NIMCustomAttachment
协议的 NECustomAttachment 类,您需要继承该类来完成自定义消息的发送和接收。
-
创建一个继承自
NECustomAttachment
的类。示例代码如下:Swiftpublic class CustomAttachment: NECustomAttachment { public var goodsName = "name" public var goodsURL = "url" ... }
Objective-C@interface CustomAttachment : NECustomAttachment @property(nonatomic, strong)NSString *goodsName; @property(nonatomic, strong)NSString *goodsURL; ... @end
-
序列化对象并将对象发送到对端。
网络层通过数据流传输,需要将遵守 NIMCustomAttachment
协议的对象转换为数据流。在 NECustomAttachment
中已经实现了基础的序列化对象的方法。即:
public func encode() -> String {}
/**
* 序列化attachment
*
* @return 序列化后的结果,将用于透传
*/
- (NSString *)encodeAttachment;
通过重写上述方法,将对象转换为数据流,并由云信 SDK 进行投递。在实际场景中,一条自定义消息往往会附带多媒体信息,如图片,音频等,NIMCustomAttachment
同样也提供了相应的接口,您只需要实现相应接口,所有的上传下载操作都可以由云信 SDK 完成。
上传
//MARK: 上传相关接口
/**
* 是否需要上传附件
* @return 是否需要上传附件
*/
public func attachmentNeedsUpload() -> Bool {
<#code#>
}
/**
* 需要上传的附件路径
* @return 路径
*/
public func attachmentPathForUploading() -> String {
<#code#>
}
/**
* 更新附件URL
* @param urlString 附件url
*/
public func updateURL(_ urlString: String) {
<#code#>
}
#pragma mark - 上传相关接口
/**
* 是否需要上传附件
* @return 是否需要上传附件
*/
- (BOOL)attachmentNeedsUpload;
/**
* 需要上传的附件路径
* @return 路径
*/
- (NSString *)attachmentPathForUploading;
/**
* 更新附件URL
* @param urlString 附件url
*/
- (void)updateAttachmentURL:(NSString *)urlString;
下载
//MARK: 下载相关接口
/**
* 是否需要下载附件
* @return 是否需要上传附件
*/
public func attachmentNeedsDownload() -> Bool {
<#code#>
}
/**
* 需要下载的附件url
* @return 附件url
*/
public func attachmentURLStringForDownloading() -> String {
<#code#>
}
/**
* 需要下载的附件本地路径
* @return 附件本地路径
* @discussion 上层需要保证路径的
*/
public func attachmentPathForDownloading() -> String {
<#code#>
}
#pragma mark - 下载相关接口
/**
* 是否需要下载附件
* @return 是否需要上传附件
*/
- (BOOL)attachmentNeedsDownload;
/**
* 需要下载的附件url
* @return 附件url
*/
- (NSString *)attachmentURLStringForDownloading;
/**
* 需要下载的附件本地路径
* @return 附件本地路径
* @discussion 上层需要保证路径的
*/
- (NSString *)attachmentPathForDownloading;
步骤 2:发送自定义消息
自定义消息的发送与其他消息类型的发送相同,直接调用 NIMChatManager
的发送接口即可。
步骤 3:接收自定义消息
与发送自定义消息不同,接收自定义消息需要上层提供额外的支持。
在构造消息时,上层需要提供将自定义消息转换二进制流的协议,同样的,当收到一条自定义消息时,需要上层提供将二进制流转换为对应的对象模型的协议。
在云信 SDK 中,通过 NIMCustomAttachmentCoding
协议支持自定义消息的反序列化。UIKit 已经提供了一个实现 NIMCustomAttachmentCoding
协议的 NECustomAttachmentDecoder 类, 您可以继承改类实现自己的反序列化逻辑。
public class CustomAttachmentDecoder: NECustomAttachmentDecoder {
override public func decodeCustomMessage(info: [String: Any]) -> CustomAttachment {
// 自定义反序列化方法之前必须调用父类的反序列化方法
let neCustomAttachment = super.decodeCustomMessage(info: info)
let customAttachment = CustomAttachment(customType: neCustomAttachment.customType,
cellHeight: neCustomAttachment.cellHeight,
data: neCustomAttachment.data)
if customAttachment.customType == 20 {
customAttachment.cellHeight = 50
}
customAttachment.goodsName = info["goodsName"] as? String ?? ""
customAttachment.goodsURL = info["goodsURL"] as? String ?? ""
return customAttachment
}
}
@interface CustomAttachmentDecoder : NECustomAttachmentDecoder
@end
@implementation CustomAttachmentDecoder
- (CustomAttachment *)decodeCustomMessageWithInfo:(NSDictionary<NSString *, id> *)info {
// 必须调用父类的反序列化方法
NECustomAttachment *neCustomAttachment = [super decodeCustomMessageWithInfo:info];
CustomAttachment *customAttachment = [[CustomAttachment alloc] initWithCustomType:neCustomAttachment.customType
cellHeight:neCustomAttachment.cellHeight
data:neCustomAttachment.data];
if (customAttachment.customType == 20) {
customAttachment.cellHeight = 50;
}
customAttachment.goodsName = info[@"goodsName"] ?: @"";
customAttachment.goodsURL = info[@"goodsURL"] ?: @"";
return customAttachment;
}
@end
最后还需要在 - (BOOL)application: didFinishLaunchingWithOptions:
中注入以下内容:
//注册自定义消息的解析器
NIMCustomObject.registerCustomDecoder(CustomAttachmentDecoder())
[NIMCustomObject registerCustomDecoder:[[CustomAttachmentDecoder alloc] init]];
后续步骤
如果需要在会话界面添加发送自定义消息的 UI 控件,可在点击【更多】按钮(见下图)后展示的区域增加相应的按钮。