即时通讯
  • 平台类型
  • 框架 / 引擎
  • iOS
  • Android
  • macOS
  • Windows
  • Linux
  • Web
  • 小程序

实现基本消息收发

更新时间:2021-09-07 16:23

本文介绍如何使用 ZIM SDK 快速实现基本的消息收发功能。

1 方案介绍

ZIM SDK 提供了如下接入方案:

/Pics/ZIM/quick_start_Structure.png

在此方案中,您需要通过您自己的业务系统实现以下业务逻辑:

  • 搭建客户端的用户管理逻辑,并下发用户 ID 用于客户端登录。
  • 鉴权 Token,建议由您的业务后台自行实现,保证鉴权数据安全。

2 前提条件

在使用 ZIM SDK 前,请确保:

  • 请联系 ZEGO 技术支持,申请需要接入 SDK 服务所需的 AppID 和 ServerSecret。
  • 请先获取登录 SDK 所需的 Token,详情请参考 使用 Token 鉴权
  • 开发环境满足以下要求:
    • Xcode 5.0 或以上版本。
    • iOS 9.0 或以上版本,且支持音视频功能的 iOS 真机设备。

3 集成 SDK

3.1 (可选)新建项目

此步骤以如何创建新项目为例,如果是集成到已有项目,可忽略此步。
  1. 启动 Xcode,在 “Welcome to Xcode” 窗口中单击 “Create a new Xcode project” 或选择 “File > New > Project” 菜单。在出现的表单中,选择 iOS 平台,并在 “Application” 下选择 “App”。

  2. 填写表单并选取各个选项来配置项目,完成后,单击 “Next”。

    必须提供 “Product Name” 和 “Organization Identifier”,用于创建 App 的唯一标识 “Bundle Identifier”。

  3. 选择项目存储路径,单击 “Create” 创建项目。

3.2 导入 SDK

开发者可通过以下任意一种方式实现集成 SDK。

方式一: 使用 CocoaPods 自动集成

  1. 安装 CocoaPods,安装时的常见问题请参考 CocoaPods 常见问题 - 安装 CocoaPods

  2. 打开终端,进入项目根目录,执行 pod init 命令创建 Podfile 文件。

  3. 打开 Podfile 文件,在 “target” 下添加 pod 'ZIM',需要将 “MyProject” 替换为开发者的 Target 名称。

    由于 SDK 为 XCFramework,只有 1.10.0 或以上版本的 CocoaPods 才能集成该 SDK。

    target 'MyProject' do
        use_frameworks!
        pod 'ZIM'
    end
  4. 执行 pod repo update 命令更新本地索引,确保能安装最新版本的 SDK,最新版本号请参考 发布日志

  5. 执行 pod install 命令安装 SDK。

方式二:复制 SDK 文件手动集成

  1. 请参考 下载 SDK,下载最新版本的 SDK。

  2. 将 SDK 包解压至项目目录下,例如 “libs” 文件夹下。

    /Pics/ZIM/iOS/directory.png

  3. 选择 “TARGETS > General > Frameworks,Libraries,and Embedded Content” 菜单,添加 “ZIM.xcframework”,将 “Embed” 设置为 “Embed & Sign”。

    /Pics/ZIM/iOS/embed_and_Sign.png

4 实现基本收发消息

以下流程中,我们以客户端 A 和 B 的消息交互为例:

/Pics/ZIM/quick_start_Implementation.png

4.1 实现流程

请参考 跑通示例源码 获取源码,相关功能的源码请查看 “ZIMExampleLegacy/Peer/ZGPeerChatViewController.m” 的文件。

1. 导入头文件

在项目文件中引入头文件 “ZIM.h”。

#import "ZIM/ZIM.h"

2. 创建 ZIM 实例

首先我们需要在 SDK 中创建 ZIM 实例,一个实例对应的是一个用户,表示一个用户以客户端的身份登录系统。

例如,客户端 A、B 分别调用 create 接口,传入在 2 前提条件 中获取到的 AppID,创建了 A、B 的实例:

// 创建 
// 创建 ZIM 对象,传入 APPID
ZIM *zim = [ZIM create:(unsigned int)appID]; 
// 将 (unsigned int)appID 替换为您申请的AppID
ZIM 创建单例的示例

由于大多数开发者,在整个流程中,只需要将 ZIM 实例化一次,因此 ZEGO 建议您将 ZIM 单例化并保存。

创建一个 ZGZIMManager 类,在该类中声明并实现了一个 “shared” 类方法,该方法将会在首次调用时创建并返回一个 ZGZIMManager 的对象,在该对象中实例化 ZIM 并保存,此后在项目的任意位置导入 ZIMManager.h 头文件,调用 “[ZGZIMManager shared].zim” 将会返回 zim 对象。

#import <Foundation/Foundation.h>
#import "ZIM/ZIM.h"
NS_ASSUME_NONNULL_BEGIN

@interface ZGZIMManager : NSObject
@property (nonatomic, strong) ZIM *zim;
+ (ZGZIMManager *)shared;

@end

NS_ASSUME_NONNULL_END
#import "ZGZIMManager.h"
static ZGZIMManager *_sharedManager = nil;
@interface ZGZIMManager ()
@end
@implementation ZGZIMManager
+ (ZGZIMManager *)shared {
    if (!_sharedManager) {
        @synchronized (self) {
            if (!_sharedManager) {
                _sharedManager = [[self alloc] init];
                _sharedManager.zim = [ZIM create:123]; //将此处 123 替换成自己的 APPID
            }
        }
    }
    return _sharedManager;
}

@end

3. 使用 EventHandler 协议

在客户端登录前,开发者需要先声明 ZIMEventHandler 协议,然后通过调用 setEventHandler 接口并实现协议中的各个方法,来设置自定义 ZIM 中的事件回调,接收到 SDK 异常、消息通知回调等的通知。

下图以在 ViewContorller 文件中,设置自定义连接状态改变为例。

/Pics/ZIM/iOS/viewcontorller_h.png
/Pics/ZIM/iOS/viewcontorller_m.png

[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 receivePeerMessage:(NSArray<ZIMMessage *> *)messageList fromUserID:(NSString *)fromUserID {
    // 接收 1v1 通信的消息回调,登录后可通过该回调接收 1v1 通信的消息  
}

- (void)zim:(ZIM *)zim
    receiveRoomMessage:(NSArray<ZIMMessage *> *)messageList
            fromRoomID:(NSString *)fromRoomID{
    // 接收房间消息回调,登录并进入房间后可通过该回调接收房间消息  
}

- (void)zim:(ZIM *)zim
    roomMemberJoined:(NSArray<ZIMUserInfo *> *)memberList
              roomID:(NSString *)roomID{
    // 接收房间成员加入回调,登录并进入房间后可以通过该回调收到房间成员进入的消息
}

- (void)zim:(ZIM *)zim
    roomMemberLeft:(NSArray<ZIMUserInfo *> *)memberList
            roomID:(NSString *)roomID{
    // 接收房间成员退出回调,登录并进入房间后可以通过该回调收到房间成员退出房间的消息
}

4. 登录 ZIM

创建实例后,客户端 A 和 B 需要登录 ZIM,只有登录成功后才可以开始发送、接收消息、更新 Token 等。

登录时,客户端需要使用各自的 userID 和 Token 进行登录,调用 login 接口进行登录,登录时 SDK 会进行鉴权(请参考 使用 Token 鉴权),鉴权通过后才能登录成功。

首先创建客户端的用户个人信息对象 ZIMUserInfo

ZIMUserInfo *userInfo = [[ZIMUserInfo alloc]init];
userInfo.userID = @""; //填入NSString类型的值
userInfo.username = @"";//填入NSString类型的值

创建完毕后,客户端可以调用 login 接口登录 ZIM。

// 登录时,需要开发者 按照 基础功能中的 "使用 Token 鉴权" 文档生成 token 即可
 [zim login:userInfo token:token ^(ZIMError * _Nonnull errorInfo) {
    //这里填写登录的回调
}];

5. 发送消息

客户端 A 登录成功后,可以向客户端 B 发送消息。目前 ZIM 支持的消息类型如下:

消息类型 描述
ZIMMessage

基类消息,包含如下属性:

  • timestamp:发送时间
  • userID:消息发送者
  • priority:优先级
  • type:消息类型
  • messageID:消息 ID
ZIMTextMessage 文本消息,是在基类的基础上添加了一个 String 类型的 message 参数,消息大小不超过 32 KB。
ZIMCustomMessage 开发者可自定义的二进制消息,例如图片、音频、视频等。自定义消息是在基类的基础上添加了一个 Byte/Data 类型的 message 参数,消息大小不超过 32 KB。

客户端 A 可以调用 sendPeerMessage 接口,传入客户端 B 的 userID、消息内容等信息,即可发送一条消息到 B 的客户端,同时可以通过 ZIMMessageSentCallback 接口的回调信息,判断消息是否发送成功。

// 发送 1v1 通信信息
ZIMTextMessage *zimMessage = [[ZIMTextMessage alloc]init];
zimMessage.message = @"消息内容";
zimMessage.priority = ZIMMessagePriorityMedium; //设置消息的优先级
[zim sendPeerMessage:zimMessage toUserID:userID callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
    //这里写发送消息后的回调
    //toUserID填这条消息接收者的 userID
}];

6. 接收消息

客户端 B 登录 ZIM 后,将会收到在 setEventHandler 回调中设置的 receivePeerMessage 监听接口,收到客户端 A 发送过来的消息。

收到消息时,由于类型是基类,首先需要判断消息类型是 Text 还是 Custom,开发者需要强转基类为具体的子类,然后从 message 字段获取消息内容。

- (void)zim:(ZIM *)zim
    receivePeerMessage:(NSArray<ZIMMessage *> *)messageList
            fromUserID:(NSString *)fromUserID{
          for(ZIMMessage *message in messageList){
        if (message.type == ZIMMessageTypeText){
            ZIMTextMessage *textMessage = (ZIMTextMessage *)message;
        }
        else if (message.type == ZIMMessageTypeCustom){
            ZIMCustomMessage *customMessage = (ZIMCustomMessage *)message;  
        }       
    }
}

7. 退出登录

如果客户端需要退出登录,直接调用 logout 接口即可。

[zim logout];

8. 销毁 ZIM 实例

如果不需要 ZIM 实例,可直接调用 destroy 接口,销毁实例。

[zim destroy];

4.2 API 时序图

通过以上的实现流程描述,可以绘制出如下 API 接口调用时序图:

相关文档