实现基本消息收发
本文介绍如何使用 ZIM SDK 快速实现基本的单聊会话消息收发功能。
1 前提条件
在使用 ZIM SDK 前,请确保:
-
开发环境满足以下要求:
- Xcode 13 或以上版本。
- iOS 11.0 或以上版本,且支持音视频功能的 iOS 真机设备。
-
已在 ZEGO 控制台 创建项目,获取到了接入 ZIM SDK 服务所需的 AppID、AppSign。ZIM 服务权限不是默认开启的,使用前,请先在 ZEGO 控制台 自助开通 ZIM 服务(详情请参考 项目管理 - 即时通讯),若无法开通 ZIM 服务,请联系 ZEGO 技术支持开通。
2.3.0 及以上
版本的 SDK,开始支持 “AppSign 鉴权”,同时仍支持 “Token 鉴权”,若您需要升级鉴权方式,可参考 ZIM 如何从 AppSign 鉴权升级为 Token 鉴权。
2 集成 SDK
2.1 (可选)新建项目
2.2 导入 SDK
开发者可通过以下任意一种方式实现集成 SDK。
方式一: 使用 Swift Package Manager 自动集成
-
打开 Xcode 并点击菜单栏 “File > Add Packages...”,在 “Apple Swift Packages” 弹窗的 “Search or Enter Package URL” 输入框中填写如下 URL 并敲击回车键确认:
Untitledhttps://github.com/zegolibrary/zim-ios
1 -
在 “Dependency Rule” 中指定你想要集成的 SDK 版本(建议使用默认的 “Up to Next Major Version”),然后点击 “Add Package“ 导入 SDK。你也可以参考 Apple 官方文档 进行设置。
方式二: 使用 CocoaPods 自动集成
-
安装 CocoaPods,安装时的常见问题请参考 CocoaPods 常见问题 - 安装 CocoaPods。
-
打开终端,进入项目根目录,执行
pod init
命令创建 Podfile 文件。 -
打开 Podfile 文件,在 “target” 下添加
pod 'ZIM'
,需要将 “MyProject” 替换为开发者的 Target 名称。注意由于 SDK 为 XCFramework,只有 1.10.0 或以上版本的 CocoaPods 才能集成该 SDK。
Untitledtarget 'MyProject' do use_frameworks! pod 'ZIM' end
1 -
执行
pod repo update
命令更新本地索引,确保能安装最新版本的 SDK,最新版本号请参考 发布日志。 -
执行
pod install
命令安装 SDK。说明- 若出现 “CDN: trunk URL couldn't be downloaded” 问题,请参考 CocoaPods 常见问题 - 连接不上 trunk CDN 的问题。
- 若出现 “Unable to find a specification for 'ZIM'” 问题,请参考 CocoaPods 常见问题 - 无法找到项目的问题。
- 若出现 “CocoaPods could not find compatible versions for pod "ZIM"” 问题,请参考 CocoaPods 常见问题 - 无法找到项目的问题。
方式三:复制 SDK 文件手动集成
-
请参考 下载 SDK,下载最新版本的 SDK。
-
将 SDK 包解压至项目目录下,例如 “libs” 文件夹下。
- 选择 “TARGETS > General > Frameworks,Libraries,and Embedded Content” 菜单,添加 “ZIM.xcframework”,将 “Embed” 设置为 “Embed & Sign”。
3 实现基本收发消息
以下流程中,我们以客户端 A 和 B 的消息交互为例:
3.1 实现流程
请参考 跑通示例源码 获取源码,相关功能的源码请查看 “ZIMExampleLegacy/Peer/ZGPeerChatViewController.m” 的文件。
1. 导入头文件
在项目文件中引入头文件 “ZIM.h”。
#import "ZIM/ZIM.h"
2. 创建 ZIM 实例
首先我们需要在 SDK 中创建 ZIM 实例,一个实例对应的是一个用户,表示一个用户以客户端的身份登录系统。
例如,客户端 A、B 分别调用 createWithAppConfig 接口,传入在 1 前提条件 中获取到的 AppID、AppSign,创建了 A、B 的实例:
2.3.0 及以上
版本的 SDK,开始支持 “AppSign 鉴权”,同时仍支持 “Token 鉴权”,若您需要升级鉴权方式,可参考 ZIM 如何从 AppSign 鉴权升级为 Token 鉴权。
// 创建 ZIM 对象,传入 appID、appSign
// 请注意:ZIM 从 2.3.0 版本开始支持 AppSign 鉴权,SDK 也默认为 AppSign 鉴权,如果您需要切换鉴权方式:
// (1) 2.3.3 及以上版本的 SDK,支持鉴权方式的自主切换; (2) 2.3.0 ~ 2.3.1 版本的 SDK,需要切换为 “Token 鉴权” 时,请联系 ZEGO 技术支持处理
ZIMAppConfig *appConfig = [[ZIMAppConfig alloc] init];
appConfig.appID = (unsigned int)appID; //替换为您申请到的 AppID
appConfig.appSign = @"appSign"; //替换为您申请到的 AppSign
self.zim = [ZIM createWithAppConfig: appConfig];
3. 使用 EventHandler 协议
在客户端登录前,开发者需要先声明 ZIMEventHandler
协议,然后通过调用 setEventHandler 接口并实现协议中的各个方法,来设置自定义 ZIM 中的事件回调,接收到 SDK 异常、消息通知回调等的通知。
下图以在 ViewContorller 文件中,设置自定义连接状态改变为例。
[zim setEventHandler:self];
- (void)zim:(ZIM *)zim errorInfo:(ZIMError *)errorInfo{
// 接收错误码的回调,通过该回调可以收到 sdk 的通用错误码。
}
- (void)zim:(ZIM *)zim tokenWillExpire:(unsigned int)second{
// 用于提示 token 即将过期,开发者可以通过该回调监听 token 快要过期的通知,自定义应对这一事件的 UI 状态
}
- (void)zim:(ZIM *)zim connectionStateChanged:(ZIMConnectionState)state event:(ZIMConnectionEvent)event extendedData:(NSDictionary *)extendedData {
// 连接状态变化通知,开发者可以通过该回调监听当前的登录连接状态,展示对应的 UI 状态
}
- (void)zim:(ZIM *)zim
peerMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromUserID:(NSString *)fromUserID {
// 接收 1v1 通信的消息回调,登录后可通过该回调接收 1v1 通信的消息
}
详细的接口介绍,请参考 tokenWillExpire、connectionStateChanged、receivePeerMessage。
4. 登录 ZIM
创建实例后,客户端 A 和 B 需要登录 ZIM,只有登录成功后才可以开始发送、接收消息、更新 Token 等。
首先,请创建用户个人登录配置(ZIMLoginConfig 对象);创建完毕后,调用 loginWithUserID 接口,传入上述对象,即可登录 ZIM。
- “userID”、“userName” 支持开发者自定义规则生成。建议开发者将 “userID” 设置为一个有意义的值,可将其与自己的业务账号系统进行关联。
- 如果你使用的是 “AppSign 鉴权”(默认),ZIMLoginConfig.Token 请保持为空。
- 如果您使用的是 “Token 鉴权”,请参考 使用 Token 鉴权 文档,获取 Token 后,并在登录 ZIM 时传入 ZIMLoginConfig.Token,鉴权通过后才能登录成功。
// 请将以下代码替换为 loginWithUserID 的调用示例
// userID 最大 32 字节的字符串。仅支持数字,英文字符 和 '!', '#', '$', '%', '&', '(', ')', '+', '-', ':', ';', '<', '=', '.', '>', '?', '@', '[', ']', '^', '_', '{', '}', '|', '~'。
// userName 最大 256 字节的字符串,无特殊字符限制。
ZIMUserInfo *userInfo = [[ZIMUserInfo alloc]init];
userInfo.userID = @"zegoUser1"; // 填入 NSString 类型的值
userInfo.userName = @"zegotest"; // 填入 NSString 类型的值
// 登录时:
// 使用 Token 鉴权,需要开发者填入 "使用 Token 鉴权" 文档生成的 Token,详情请参考 [使用 Token 鉴权]
// 使用 AppSign 鉴权 (2.3.0 或以上版本的默认鉴权方式),Token 参数填空字符串
[zim loginWithUserInfo:userInfo callback:^(ZIMError * _Nonnull errorInfo) {
//这里填写登录的回调
}];
5. 发送消息
客户端 A 登录成功后,可以向客户端 B 发送消息。
目前 ZIM 支持的消息类型如下:
消息类型 | 说明 | 特性及适用场景 |
---|---|---|
ZIMTextMessage(1) | 文本消息。消息大小不超过 32 KB,单个客户端发送频率限制为 10 次/秒。 | 消息可靠有序,可存储为历史消息(保存时间请参考 计费说明 - 版本说明 中“历史消息存储天数”。); 一般适用于“单聊”、“群聊”等即时聊天的场景和“房间聊天”的公屏聊天场景。房间解散后,“房间聊天”的消息不存储。 相关接口:sendMessage |
ZIMCommandMessage(2) | 开发者可自定义数据内容的信令消息。消息大小不超过 5 KB,单个客户端发送频率限制为 10 次/秒。 | 不可存储,支持更高的并发;一般适用于“语聊房”、“在线课堂”等房间内的信令传输,比如上下麦操作、送礼物,发送在线课堂课件等。 相关接口:sendMessage |
ZIMBarrageMessage(20) | 房间内弹幕文本消息。消息大小不超过 5 KB,单个客户端发送频率无限制。 | 不可存储,专门用于房间内的高频、不可靠、允许丢掉的消息,一般适用于发送“弹幕消息”的场景中。 支持高并发,但不可靠,不保证消息送达。 相关接口:sendMessage |
ZIMImageMessage(11) | 图片消息。支持主流图片格式,包括 JPG、PNG、BMP、TIFF、GIF、WebP,大小不超过 10 MB,单个客户端发送频率限制为 10 次/秒。 | 消息可靠有序,可存储为历史消息(保存时间请参考 计费说明 - 版本说明 中“历史消息存储天数”。); 一般用于单聊、房间、群聊等即时聊天场景。 相关接口: sendMediaMessage |
ZIMFileMessage(12) | 文件消息。消息内容为文件,格式不限,大小不超过 100 MB,单个客户端发送频率限制为 10 次/秒。 | |
ZIMAudioMessage(13) | 语音消息。支持 MP3、M4A 格式的语音文件,时长不超过 300 秒,大小不超过 6 MB,单个客户端发送频率限制为 10 次/秒。 | |
ZIMVideoMessage(14) | 视频消息。支持 MP4、MOV 格式的视频文件,大小不超过 100 MB,单个客户端发送频率限制为 10 次/秒。仅支持视频编码格式为 H264 和 H265 的视频文件在消息发送成功后获取该视频首帧的宽、高信息。 | |
ZIMCombineMessage(100) | 合并消息,消息大小无限制,单个客户端发送频率限制为 10 次/秒。 | 消息可靠有序,可存储为历史消息(保存时间请参考 计费说明 - 版本说明 中“历史消息存储天数”。); 一般用于单聊、房间、群聊等即时聊天场景。 相关接口:sendMessage |
ZIMCustomMessage(200) | 自定义消息。开发者可自定义消息的类型,并自行完成消息的解析,ZIM SDK 不负责定义和解析自定义消息的具体内容。 | 消息可靠有序,可存储为历史消息(保存时间请参考 计费说明 - 版本说明 中“历史消息存储天数”。); 一般可用于发送投票类型、接龙类型、视频卡片类型等消息。 相关接口: sendMessage |
以下为发送单聊文本消息
为例:客户端 A 可以调用 sendMessage 接口,传入客户端 B 的 userID、消息内容、消息类型 conversationType 等参数,即可发送一条文本消息
到 B 的客户端。
- ZIMMessageSentCallback 回调,判断消息是否发送成功。
- onMessageAttached 回调,在消息发送前,可以获得一个临时的 ZIMMessage,以便您添加一些业务处理逻辑。例如:在发送消息前,获取到该条消息的 ID 信息。开发者在发送“视频”等内容较大的消息时,可以在消息上传完成前,获取对应该条消息的 localMessageID,实现发送前 Loading 的效果。
// 以下以发送单聊信息为例,conversationType 设置为 ZIMConversationTypePeer
ZIMTextMessage *zimMessage = [[ZIMTextMessage alloc]init];
zimMessage.message = @"消息内容";
ZIMMessageSendNotification *notification = [[ZIMMessageSendNotification alloc] init];
notification.onMessageAttached = ^(ZIMMessage * _Nonnull message) {
// 发送前的回调,客户可以在这里获取一个临时对象,该对象与开发者创建的 zimMessage 对象属于同一对象,开发者可利用此特性做一些业务逻辑,如提前展示 UI 等
};
ZIMMessageSendConfig *config = [[ZIMMessageSendConfig alloc] init];
config.priority = ZIMMessagePriorityMedium; // 消息优先级,取值为 低:1 默认,中:2,高:3
// 单聊时,conversationID 即是对方的 userID;群组时,conversationID 即是群组的 groupID;房间时,conversationID 即是房间的 roomID
[zim sendMessage:zimMessage toConversationID:conversationID conversationType:ZIMConversationTypePeer config:config notification:notification callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
// 这里写发送消息后的回调
// toUserID 填这条消息接收者的 userID
}];
6. 接收消息
客户端 B 登录 ZIM 后,将会收到在 setEventHandler 回调中设置的 receivePeerMessage 监听接口,收到客户端 A 发送过来的消息。
收到消息时,由于类型是基类,首先需要判断消息类型是 Text 还是 Command,开发者需要强转基类为具体的子类,然后从 message 字段获取消息内容。
- (void)zim:(ZIM *)zim
peerMessageReceived:(NSArray<ZIMMessage *> *)messageList
info:(ZIMMessageReceivedInfo *)info
fromUserID:(NSString *)fromUserID{
for(ZIMMessage *message in messageList){
if (message.type == ZIMMessageTypeText){
ZIMTextMessage *textMessage = (ZIMTextMessage *)message;
}
else if (message.type == ZIMMessageTypeCommand){
ZIMCommandMessage *commandMessage = (ZIMCommandMessage *)message;
}
}
}
7. 退出登录
如果客户端需要退出登录,直接调用 logout 接口即可。
[zim logout];
8. 销毁 ZIM 实例
如果不需要 ZIM 实例,可直接调用 destroy 接口,销毁实例。
[zim destroy];
3.2 API 时序图
通过以上的实现流程描述,API 接口调用时序图如下:
- 发送消息时,统一使用 sendMessage 接口,并根据消息类型传入对应的 conversationType 取值。
- 接收消息时:
- 单聊消息(Peer 类型),通过 receivePeerMessage 回调接收。
- 房间消息(Room 类型),通过 receiveRoomMessage 回调接收。
- 群组消息(Group 类型),通过 receiveGroupMessage 回调接收。