In-app Chat
  • iOS : Objective-C
  • Android
  • macOS
  • Windows
  • Web
  • Flutter
  • React Native
  • Introduction
    • Overview
    • Basic concepts
  • Sample app
  • Getting started
  • Client SDKs
    • SDK downloads
    • Release notes
  • Guides
    • Authentication
    • Manage users
    • Room
    • Group
    • Messaging
    • Call invitation (signaling)
    • Manage sessions
  • Offline push notifications
  • Error codes
  • Server APIs
  • API Documents

Send and receive messages

Last updated:2022-11-14 11:22

This document describes how to use the ZIM SDK (In-app Chat) to send and receive messages.


The following shows the access solution that the ZIM SDK provides.


In this solution, you will need to implement the following business logic based on your actual business requirements:

  • The logic for managing the users on the client, and the logic for distributing user ID for users to log in.


Before you begin, make sure:

  • Go to ZEGOCLOUD Admin Console, and do the following:
    • Create a project, get the AppID and AppSign.
    • Activate the In-app Chat service (as shown in the following figure).
  • Xcode 5.0 or later
  • A real iOS device that is running on iOS 9.0 or later and supports audio and video.

Integrate the SDK

Optional: Create a project

Skip this step if a project already exists.

Create a new project
  1. Open Xcode, and in the Welcome to Xcode window, click Create a new Xcode project or select File > New > Project. In the dialog that appears, select the iOS tab, then select App in the Application section.

  2. Fill in items or choose options for the new project, click Next after configuration is completed.

    Product Name and Organization Identifier are required, which will be used for creating the App UID - Bundle Identifier.

  3. Choose a particular directory to restore the project to be created, and click Create to create a project.

Import the SDK

Choose either of the following methods to integrate the SDK into your project.

Method 1: Integrate the SDK automatically with CocoaPods

  1. Install CocoaPods. For more details, see CocoaPods Installation Guide .

  2. Open the Terminal, enter the root directory of the project, and execute the command pod init to create a Podfile.

  3. Open Podfile, add pod 'ZegoExpressEngine/Video', and change MyProject to your target name.

    Because the SDK is XCFramwork, therefore, you will need to use CocoaPods 1.10.0 or later to integrate the SDK.

    target 'MyProject' do
        pod 'ZIM'
  4. Execute pod repo update to update the local index to make sure the latest version of SDK can be installed.

  5. Execute pod install to install the SDK.

    For common problems you may encounter when using CocoaPods, see CocoaPods FAQ .

Method 2: Manually add the SDK to the project

  1. Download the latest version of SDK from SDK downloads.

  2. Unzip the SDK package to the libs folder.


  3. Select the target project, click General, then under Frameworks, Libraries, and Embedded Content, add ZIM.xcframework to the target, and set the Embed field to Embed & Sign.


Implementation steps

Get the sample code

To download and run the sample code, see Sample app.

For the sample code related to this feature, check out the source files in the ZIMExampleLegacy/Peer/ZGPeerChatViewController.m directory in the SDK sample code package.

Import the header file

Import the header file ZIM.h.

#import "ZIM/ZIM.h"

Create a ZIM SDK instance

Creating a ZIM instance is the very first step, an instance corresponds to a user logging in to the system as a client.

So, let's suppose we have two clients now, client A and client B. To send and receive messages to each other, both of them will need to call the create method with the AppID in the previous Prerequisites steps to create a ZIM SDK instance of their own:

// Create a ZIM SDK instance  
//  Create a ZIM SDK object and pass your AppID and AppSign.
ZIMAppConfig *appConfig = [[ZIMAppConfig alloc] init];
appConfig.appID = (unsigned int)appID;
appConfig.appSign = @"appSign";
self.zim = [ZIM createWithAppConfig: appConfig];
The sample code to create a ZIM SDK singleton

For most cases, you will only need to create the ZIM SDK instance once. We recommend you create a singleton and save it.

Create a ZGZIMManager class, declare and implement a shared class method in this class, which will create and return a ZGZIMManager object the first time it is called, and create and save a ZIM SDK instance in this object. Then, when you import the zimManager.h header file anywhere in the project and call the [ZGZIMManager shared].zim, a ZIM object will be returned.

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

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


#import "ZGZIMManager.h"
static ZGZIMManager *_sharedManager = nil;
@interface ZGZIMManager ()
@implementation ZGZIMManager
+ (ZGZIMManager *)shared {
    if (!_sharedManager) {
        @synchronized (self) {
            if (!_sharedManager) {
                _sharedManager = [[self alloc] init];
                _sharedManager.zim = [ZIM createWithAppID:123]; //Replace the 123 with the AppID you get.
    return _sharedManager;


Conform to the EventHandler protocol

Before a client user's login, you will need to call the setEventHandler method to implement an event handler object that conforms to the ZIMEventHandler protocol (for example, self), and implement the methods involved in the protocol to receive callbacks (you can customize the event callbacks, such as you can receive callback notifications when SDK errors occur or receive message related callback notifications).

The following is the sample code for setting the event callback when connection status changes in the ViewContorller file:


[zim setEventHandler:self];

- (void)zim:(ZIM *)zim errorInfo:(ZIMError *)errorInfo{
    // The callback for receiving error codes. This callback will be triggered when SDK returns error codes. 

- (void)zim:(ZIM *)zim tokenWillExpire:(unsigned int)second{
    // The callback for Token expires. This callback will be triggered when the Token is about to expire, and you can customize a UI for this event.  
- (void)zim:(ZIM *)zim connectionStateChanged:(ZIMConnectionState)state event:(ZIMConnectionEvent)event extendedData:(NSDictionary *)extendedData {
    // The callback for connection status changes. This callback will be triggered when the connection status changes, and you can customize a UI for this event.

- (void)zim:(ZIM *)zim receivePeerMessage:(NSArray<ZIMMessage *> *)messageList fromUserID:(NSString *)fromUserID {
    // The callback for receiving one-on-one messages. You can receive message notificaitons through this callback after login. 

- (void)zim:(ZIM *)zim
    receiveRoomMessage:(NSArray<ZIMMessage *> *)messageList
            fromRoomID:(NSString *)fromRoomID{
    // The callback for receiving the in-room messages. You can receive in-room message notificaitons through this callback after login and joining a room.  

- (void)zim:(ZIM *)zim
    roomMemberJoined:(NSArray<ZIMUserInfo *> *)memberList
              roomID:(NSString *)roomID{
    // The callback for a new user joins the room. You can receive notifications when a new user joins the room through this callback after logging in and joining a room.

- (void)zim:(ZIM *)zim
    roomMemberLeft:(NSArray<ZIMUserInfo *> *)memberList
            roomID:(NSString *)roomID{
    // The callback for an existing user leaves the room. You can receive notifications when an existing user leaves the room through this callback after login and joining a room.

Log in to the ZIM SDK

For client A and client B to send and receive messages after creating the ZIM SDK instance, they will need to log in to the ZIM SDK.

To log in, Clients A and B both need to do the following:

  1. Call the ZIMUserInfo method to create a user object.
  • You can custom the userID and userName, and we recommend you set these two to a meaningful value and associate them with the account system of your application.

First, create a ZIMUserInfo object with your user information. Then, client A and client B can call the login to log in to the ZIM SDK.

// userID and userName must be within 32 bytes, and can only contain letters, numbers, and the following special characters: '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '=', '-', '`', ';', '’', ',', '.', '<', '>', '/', '\'.
ZIMUserInfo *userInfo = [[ZIMUserInfo alloc]init];
userInfo.userID = @"zegoUser1"; //Fill in a NSString type value. 
userInfo.userName = @"zegotest";//Fill in a NSString type value. 

[zim loginWithUserInfo:userInfo callback:^(ZIMError * _Nonnull errorInfo) {
    //Implement a callback for login here. 

Send messages

Client A can send messages to client B after logging in successfully.

Currently, the ZIM SDK supports the following message types:

Message type Description Details
Text message. Size limit: 32 KB. Rate limit: 10 requests/second.
Enable messages to be more deliverable, and can be stored as message history. Suitable for one-on-one chat and group chat.
Customizable signaling message. Size limit: 5 KB. Rate limit: 10 requests/second.
Supports massive concurrency. Suitable for live audio room, online classroom, the messages won't be stored after the room is destroyed.
In-room barrage messgae (bullet) screen message). Size limit: 5 KB. No specific rate limit.
The high-frequency messages that doesn't require 100% deliverability, this message type is often be used to send bullet screen messages.

Supports massive concurrency, but the message deliverability can't be guaranteed.

Image message. Supports major image formats, including JPG, PNG, BMP, TIFF, and GIF. Size limit: 10 MB. Rate limit: 10 requests/second.
Enable messages to be more deliverable, and can be stored as history message. Suitable for one-on-one chat, room chat, and group chat.
File message. Supports files in any format. Size limit: 10 MB. Rate limit: 10 requests/second.
Voice message. Supports voice message in MP3 format that within 300 seconds. Size limit: 6 MB. Rate limit: 10 requests/second.
Video message. Supports video message in MP4 or MOV format. Size limit: 100 MB. Rate limit: 10 requests/second.

To send one-to-one messages, for example, client A wants to send a message to client B, then client A needs to call the sendPeerMessage method with client B's userID, message content, and other info. And client A can be notified whether the message is delivered successfully through the callback ZIMMessageSentCallback.

// Send one-to-one messages. 
ZIMTextMessage *zimMessage = [[ZIMTextMessage alloc]init];
zimMessage.message = @"Message content";
ZIMMessageSendConfig *config = [[ZIMMessageSendConfig alloc] init];
config.priority = ZIMMessagePriorityMedium; //Set priority for the message. 1: Low (by default). 2: Medium. 3: High.
[zim sendPeerMessage:zimMessage toUserID:userID config:config callback:^(ZIMMessage * _Nonnull message, ZIMError * _Nonnull errorInfo) {
    //Implement the event callback for send messages here.
    //toUserID refers to the userID of the message receiver. 

Receive messages

After client B logs in, he will receive client A's message through the callback receivePeerMessage which is already set in the setEventHandler method.

When a message is received, you need to determine the message is a Text message or a Command message because these two message types are based on the basic message. You need to convert the basic message class to a concrete message type and then retrieve the message content from the Message field.

- (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;  

Log out

For a client to log out, call the logout method.

[zim logout];

Destroy the ZIM SDK instance

To destroy the ZIM SDK instance, call the destroy method.

[zim destroy];