实现自定义消息收发

更新时间: 2024/03/15 18:26:21

前言

云信 SDK 内置了包括图片,音频,视频等多媒体消息,但用户基于自己的应用场景往往需要某些特殊的消息类型,因此需要自定义消息类型。

本文主要介绍如何从 model 到 UI,一步步实现自定义消息类型。

IM UIKit 的会话消息模块(NEChatUIKit)默认实现了文本消息、图片消息等基本消息类型的发送和展示。如果这些消息类型无法满足您的业务需求,您可新增自定义消息类型

基本消息类型

消息类型
显示效果
是否需要额外集成
文本消息 否,集成会话界面即可用
图片消息 否,集成会话界面即可用
语音消息 否,集成会话界面即可用
视频消息 否,集成会话界面即可用
表情 否,集成会话界面即可用
文件消息 否,集成会话界面即可用发送文件消息需要访问 iCloud 服务,若您的系统低于 iOS 11,则需要提前配置相关权限,否则可能会出现异常。
具体配置操作如下请在 Xcode 中选择TARGETS -> Signing&Capabilities -> iCloud,然后勾选 iCloud Documents
iCloud 权限
地理位置 是,见实现地理位置消息功能

前提条件

集成会话消息界面

实现流程

步骤 1:创建自定义消息

在云信 SDK 中,需要通过 NIMCustomObject 来实现自定义消息类型,内部包含一个实现 NIMCustomAttachment 协议的对象。UIKit 已经提供了一个实现 NIMCustomAttachment 协议的 NECustomAttachment 类,您需要继承该类来完成自定义消息的发送和接收。

  1. 创建一个继承自 NECustomAttachment 的类。示例代码如下:

    Swift
    public 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
    
  2. 序列化对象并将对象发送到对端。

网络层通过数据流传输,需要将遵守 NIMCustomAttachment 协议的对象转换为数据流。在 NECustomAttachment 中已经实现了基础的序列化对象的方法。即:

Swift
public func encode() -> String {}
Objective-C
/**
 *  序列化attachment
 *
 *  @return 序列化后的结果,将用于透传
 */
- (NSString *)encodeAttachment;

通过重写上述方法,将对象转换为数据流,并由云信 SDK 进行投递。在实际场景中,一条自定义消息往往会附带多媒体信息,如图片,音频等,NIMCustomAttachment 同样也提供了相应的接口,您只需要实现相应接口,所有的上传下载操作都可以由云信 SDK 完成。

上传

Swift
//MARK: 上传相关接口
    
/**
    *  是否需要上传附件
    *  @return 是否需要上传附件
    */
public func attachmentNeedsUpload() -> Bool {
    <#code#>
}

/**
    *  需要上传的附件路径
    *  @return 路径
    */
public func attachmentPathForUploading() -> String {
    <#code#>
}

/**
    *  更新附件URL
    *  @param urlString 附件url
    */
public func updateURL(_ urlString: String) {
    <#code#>
}
Objective-C
#pragma mark - 上传相关接口
/**
 *  是否需要上传附件
 *  @return 是否需要上传附件
 */
- (BOOL)attachmentNeedsUpload;

/**
 *  需要上传的附件路径
 *  @return 路径
 */
- (NSString *)attachmentPathForUploading;

/**
 *  更新附件URL
 *  @param urlString 附件url
 */
- (void)updateAttachmentURL:(NSString *)urlString;

下载

Swift
//MARK: 下载相关接口
    
/**
    *  是否需要下载附件
    *  @return 是否需要上传附件
    */
public func attachmentNeedsDownload() -> Bool {
    <#code#>
}

/**
    *  需要下载的附件url
    *  @return 附件url
    */
public func attachmentURLStringForDownloading() -> String {
    <#code#>
}

/**
    *  需要下载的附件本地路径
    *  @return 附件本地路径
    *  @discussion 上层需要保证路径的
    */
public func attachmentPathForDownloading() -> String {
    <#code#>
}
Objective-C
#pragma mark - 下载相关接口
/**
 *  是否需要下载附件
 *  @return 是否需要上传附件
 */
- (BOOL)attachmentNeedsDownload;

/**
 *  需要下载的附件url
 *  @return 附件url
 */
- (NSString *)attachmentURLStringForDownloading;

/**
 *  需要下载的附件本地路径
 *  @return 附件本地路径
 *  @discussion 上层需要保证路径的
 */
- (NSString *)attachmentPathForDownloading;

步骤 2:发送自定义消息

自定义消息的发送与其他消息类型的发送相同,直接调用 NIMChatManager 的发送接口即可。

步骤 3:接收自定义消息

与发送自定义消息不同,接收自定义消息需要上层提供额外的支持。

在构造消息时,上层需要提供将自定义消息转换二进制流的协议,同样的,当收到一条自定义消息时,需要上层提供将二进制流转换为对应的对象模型的协议。

在云信 SDK 中,通过 NIMCustomAttachmentCoding 协议支持自定义消息的反序列化。UIKit 已经提供了一个实现 NIMCustomAttachmentCoding 协议的 NECustomAttachmentDecoder 类, 您可以继承改类实现自己的反序列化逻辑。

Swift
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
  }
}
Objective-C
@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: 中注入以下内容:

Swift
//注册自定义消息的解析器
NIMCustomObject.registerCustomDecoder(CustomAttachmentDecoder())
Objective-C
[NIMCustomObject registerCustomDecoder:[[CustomAttachmentDecoder alloc] init]];

后续步骤

如果需要在会话界面添加发送自定义消息的 UI 控件,可在点击【更多】按钮(见下图)后展示的区域增加相应的按钮。

image
此文档是否对你有帮助?
有帮助
去反馈
  • 前言
  • 基本消息类型
  • 前提条件
  • 实现流程
  • 步骤 1:创建自定义消息
  • 步骤 2:发送自定义消息
  • 步骤 3:接收自定义消息
  • 后续步骤