QuickBlox Documentation

QuickBlox provides powerful Chat API and SDK to add real-time messaging and video calls to your web and mobile apps. Learn how to integrate QuickBlox across multiple platforms and devices. Check out our detailed guides to make integration easy and fast.

Chat

Learn how to enable chat functionality for your app.

Chat API is built on top of real-time (XMPP) protocol. In order to use it, you need to setup real-time connection with QuickBlox Chat server and use it to exchange data. By default real-time Chat works over secure TLS connection.

Before you begin

  1. Visit our Key Concepts page to get an overall understanding of the most important QuickBlox concepts.
  2. Register a QuickBlox account. This is a matter of a few minutes and you will be able to use this account to build your apps.
  3. Configure QuickBlox SDK for your app. Check out our Setup page for more details.
  4. Create a user session to be able to use QuickBlox functionality. See our Authentication page to learn how to do it.

Connect to Chat server

To connect to the Chat server use the code snippet below.

QBSettings.autoReconnectEnabled = true
QBSettings.reconnectTimerInterval = 5
QBSettings.carbonsEnabled = true
QBSettings.keepAliveInterval = 20
QBSettings.streamManagementSendMessageTimeout = 0
QBSettings.networkIndicatorManagerEnabled = false

let currentUser = QBUUser()
currentUser.ID = 56
currentUser.password = "chatUserPass"
QBChat.instance.connect(withUserID: currentUser.id, password: currentUser.password, completion: { (error) in
    
})
[QBSettings setAutoReconnectEnabled:YES];
[QBSettings setReconnectTimerInterval:5];
[QBSettings setCarbonsEnabled:YES];
[QBSettings setKeepAliveInterval:20];
[QBSettings setStreamManagementSendMessageTimeout:0];
[QBSettings setNetworkIndicatorManagerEnabled:NO];

QBUUser *currentUser = [QBUUser user];
currentUser.ID = 56;
currentUser.password = @"chatUserPass";
[QBChat.instance connectWithUserID:currentUser.ID password:currentUser.password completion:^(NSError * _Nullable error) {
    
}];

Parameters

Description

autoReconnectEnabled

iOS SDK reconnects automatically to the Chat server when the connection to the server is lost. Default: false.

reconnectTimerInterval

A reconnect timer can optionally be used to attempt a reconnect periodically. Set in seconds. Default: 5.

carbonsEnabled

Message carbons allow for real-time message syncing between devices. Default: false.

keepAliveInterval

Keep-alive option for a socket connection. Keep-alive is the option allowing to detect a stale connection. Set in seconds. Default: 20.

streamManagementSendMessageTimeout

The timeout value for stream management. Set in seconds. If this parameter is greater than 0, then it is applied, otherwise, it is not applied. Default: 0.

networkIndicatorManagerEnabled

A boolean value indicating whether the manager is enabled. If true, the manager will change status bar network activity indicator according to network operation notifications it receives. Default: false.

Use QBChatDelegate to handle different connection states.

class YourClass : NSObject {
    QBChat.instance.addDelegate(self)
}
// MARK: QBChatDelegate
extension YourClass : QBChatDelegate {
    func chatDidConnect() {
    }
    func chatDidReconnect() {
    }
    func chatDidDisconnectWithError(_ error: Error?) {
    }
    func chatDidNotConnectWithError(_ error: Error) {
    }
}
@interface YourClass () <QBChatDelegate>
@end

@implementation YourClass
- (instancetype)init {
    self = [super init];
    if (self) {
        [QBChat.instance addDelegate:self];
    }
    return self;
}
// MARK: QBChatDelegate
- (void)chatDidConnect {
}
- (void)chatDidReconnect {
}
- (void)chatDidDisconnectWithError:(NSError *)error {
}
- (void)chatDidNotConnectWithError:(NSError *)error {
}
- (void)chatDidFailWithStreamError:(NSError *)error {
}

@end;

Disconnect from Chat server

Disconnect from the Chat server using the snippet below.

QBChat.instance.disconnect { (error) in
    
}
[QBChat.instance disconnectWithCompletionBlock:^(NSError * _Nullable error) {
    
}];

Autoreconnect to Chat

The SDK reconnects automatically when the connection to the Chat server is lost. There is a way to disable it and then manage it manually.

QBSettings.autoReconnectEnabled = false
QBSettings.autoReconnectEnabled = NO;

Chat in background

To handle chat offline messages correctly do disconnect() when an app goes to background and connect() when an app goes to the foreground.

class AppDelegate: UIResponder, UIApplicationDelegate {
    // ...
    func applicationWillTerminate(_ application: UIApplication) {
        QBChat.instance.disconnect { (error) in
        }
    }
    func applicationDidEnterBackground(_ application: UIApplication) {
        QBChat.instance.disconnect { (error) in
        }
    }
    func applicationWillEnterForeground(_ application: UIApplication) {
        QBChat.instance.connect(withUserID: currentUser.ID, password: currentUser.password) { (error) in
        }
    }
    // ...
}
@implementation AppDelegate
// ...
- (void)applicationWillTerminate:(UIApplication *)application {
    [QBChat.instance disconnectWithCompletionBlock:^(NSError * _Nullable error) {
    }];
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
    [QBChat.instance disconnectWithCompletionBlock:^(NSError * _Nullable error) {
    }];
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
    [QBChat.instance connectWithUserID:currentUser.ID password:currentUser.password completion:^(NSError * _Nullable error) {
    }];
}
// ...

Dialogs

All chats between users are organized in dialogs. There are 3 types of dialogs:

  • 1-1 dialog - a conversation between 2 users.
  • group dialog - a conversation between the specified list of users.
  • public dialog - an open conversation. Any user from your app can subscribe to it.

You need to create a new dialog and then use it to chat with other users. You also can obtain a list of your existing dialogs.

Create new dialog

Create 1-1 dialog

You need to pass private as a dialog type and ID of an opponent you want to create a chat with.

let dialog = QBChatDialog(dialogID: nil, type: .private)
dialog.occupantIDs = [34]
QBRequest.createDialog(dialog, successBlock: { (response, createdDialog) in

}, errorBlock: { (response) in
    
})
QBChatDialog *dialog = [[QBChatDialog alloc] initWithDialogID:nil type:QBChatDialogTypePrivate];
dialog.occupantIDs = @[@34]; // an ID of opponent
[QBRequest createDialog:dialog successBlock:^(QBResponse * _Nonnull response, QBChatDialog * _Nonnull createdDialog) {
        
} errorBlock:^(QBResponse * _Nonnull response) {
        
}];

Create group dialog

You need to pass QuickBlox DialogType.GROUP as a type and IDs of opponents, you want to create a chat with.

let chatDialog = QBChatDialog(dialogID: nil, type: .group)
chatDialog.name = "New group dialog"
chatDialog.occupantIDs = [34, 45, 55]
        
QBRequest.createDialog(chatDialog, successBlock: { (response, dialog) in
    dialog.join(completionBlock: { (error) in  
    })
}, errorBlock: { (response) in
    
})
QBChatDialog *chatDialog = [[QBChatDialog alloc] initWithDialogID:nil type:QBChatDialogTypeGroup];
chatDialog.name = @"Group dialog name";
chatDialog.occupantIDs = @[@34, @45, @55];

[QBRequest createDialog:chatDialog successBlock:^(QBResponse * _Nonnull response, QBChatDialog * _Nonnull dialog) {
    [dialog joinWithCompletionBlock:^(NSError * _Nullable error) {
        
    }];
} errorBlock:^(QBResponse * _Nonnull response) {

}];

Create public dialog

It's possible to create a public dialog, so any user from your application can subscribe to it. There is no a list with occupants, this dialog is just open for everybody. You need to specify public as a dialog type within the QBChatDialog instance.

let dialog = QBChatDialog(dialogID: nil, type: .public)
dialog.name = "Public dialog name"
dialog.dialogDescription = "Public dialog description"
// dialog.photo = "...";
    
QBRequest.createDialog(chatDialog, successBlock: { (response, dialog) in
    dialog.join(completionBlock: { (error) in  
    })                                             
}, errorBlock: { (response) in
    
})
QBChatDialog *dialog = [[QBChatDialog alloc] initWithDialogID:nil type:QBChatDialogTypePublicGroup];
dialog.name = @"Public dialog name";
dialog.dialogDescription = @"Public dialog description";
// dialog.photo = @"...";
    
[QBRequest createDialog:chatDialog successBlock:^(QBResponse * _Nonnull response, QBChatDialog * _Nonnull dialog) {
    [dialog joinWithCompletionBlock:^(NSError * _Nullable error) {
        
    }];
} errorBlock:^(QBResponse * _Nonnull response) {

}]

Retrieve list of dialogs

It's common to request all your conversations on every app login. The request below will return all 1-1 dialogs, group dialog, and public dialogs you are subscribed to.

QBRequest.dialogs(for: QBResponsePage(limit: 50, skip: 100), extendedRequest: nil, successBlock: { (response, dialogs, dialogsUsersIDs, page) in

}, errorBlock: { (response) in
    
})
[QBRequest dialogsForPage:[QBResponsePage responsePageWithLimit:50 skip:100] extendedRequest:nil successBlock:^( response, dialogs, dialogsUsersIDs, page) {
        
} errorBlock:^(QBResponse * _Nonnull response) {
       
}];

Filters

If you want to retrieve only dialogs updated after some specific date time, you can pass the filter. This is useful if you cache dialogs somehow and do not want to obtain the whole list of your dialogs on every app start.

You can apply filters for the following fields:

  • _id (string)
  • type (integer)
  • name (string)
  • last_message_date_sent (integer)
  • created_at (date)
  • updated_at (date)

You can apply sort for the following fields:

  • last_message_date_sent

Filter

Applicable to types

Description

{field_name}

All types

Search records with the field which contains the specified value.

{field_name}[{search_operator}]

All types

Search a record with the field which contains the value according to the specified value and operator.

sort_asc

All types

Search results will be sorted by the specified field in ascending order.

sort_desc

All types

Search results will be sorted by the specified field in descending order.

skip

Integer

Skip N records in search results. Useful for pagination. Default (if not specified): 0.

limit

Integer

Limit search results to N records. Useful for pagination. Default value: 100. If limit is equal to 1, only the last record will be returned.

count

Integer

Count search results. Response will contain only count of records found.

Search operators

Here are the search operators that you can use to retrieve dialogs.

Search operators

Applicable to types

Description

lt

Integer, Float

Less Than operator.

lte

Integer, Float

Less Than or Equal to operator.

gt

Integer, Float

Greater Than operator.

gte

Integer, Float

Greater Than or Equal to operator.

ne

Integer, Float, String, Boolean

Not Equal to operator.

in

Integer, Float, String

IN array operator.

nin

Integer, Float, String

Not IN array operator.

all

Array

ALL are contained in array.

ctn

String

All records that contain a particular substring.

Update dialog

Update a group dialog name, description or photo using update() method.

chatDialog.name = "New dialog name"
chatDialog.dialogDescription = "New dialog description"
chatDialog.photo = "https://new_photo_url" // or it can be an ID to some file in Storage module
    
QBRequest.update(chatDialog, successBlock: { (response, updatedDialog) in

}, errorBlock: { (response) in
    
})
dialog.name = @"New dialog name";
dialog.dialogDescription = @"New dialog description";
dialog.photo = @"https://new_photo_url"; // or it can be an ID to some file in Storage module

[QBRequest updateDialog:dialog successBlock:^(QBResponse * _Nonnull response, QBChatDialog * _Nonnull updatedDialog) {

} errorBlock:^(QBResponse * _Nonnull response) {

}];

❗️

Only group dialog owner can remove other users from a group dialog.

Add/Remove occupants

You can add/remove occupants in group and public dialogs.

let pushOccupantsIDs = [10056, 75432].map({ $0.stringValue })
chatDialog.pushOccupantsIDs = pushOccupantsIDs
QBRequest.update(chatDialog, successBlock: { (response, updatedDialog) in

}, errorBlock: { (response) in
    
})
dialog.pushOccupantsIDs = @[@"10056", @"75432"];
[QBRequest updateDialog:dialog successBlock:^(QBResponse * _Nonnull response, QBChatDialog * _Nonnull updatedDialog) {

} errorBlock:^(QBResponse * _Nonnull response) {

}];

❗️

Only group dialog owner can remove other users from a group dialog.

Remove dialog

The following snippet is used to delete a conversation.

QBRequest.deleteDialogs(withIDs: Set<String>(["5356c64ab35c12bd3b108a41", "d256c64ab35c12bd3b108bc5"]), forAllUsers: false, successBlock: { (deletedObjectsIDs, notFoundObjectsIDs, wrongPermissionsObjectsIDs) in
    
}, errorBlock: { (response) in
    
})
[QBRequest deleteDialogsWithIDs:[NSSet setWithArray:@[@"5356c64ab35c12bd3b108a41", @"d256c64ab35c12bd3b108bc5"]] forAllUsers:NO successBlock:^( deletedObjectsIDs, notFoundObjectsIDs, wrongPermissionsObjectsIDs) {
    
} errorBlock:^(QBResponse * _Nonnull response) {

}];

🚧

This request will remove this conversation for a current user, but other users will be still able to chat there. The forceDelete parameter is used to completely remove the dialog. Only group chat owner can remove the group dialog. You can also delete multiple conversations in a single request.

Chat history

Every chat conversation stores its chat history that you can retrieve.

let page = QBResponsePage(limit: 50, skip: 100)
let extendedRequest = ["sort_desc": "date_sent", "mark_as_read": "0"]
QBRequest.messages(withDialogID: "5356c64ab35c12bd3b108a41", extendedRequest: extendedRequest, for: page, successBlock: { (response, messages, page) in

}, errorBlock: { (response) in
    
})
QBResponsePage *responsePage = [QBResponsePage responsePageWithLimit:50 skip:0];
NSDictionary *extReq = @{@"sort_desc": @"date_sent", @"mark_as_read": @"0"};
[QBRequest messagesWithDialogID:@"5356c64ab35c12bd3b108a41" extendedRequest:extReq forPage:responsePage successBlock:^(QBResponse *response, NSArray *messages, QBResponsePage *page) {

} errorBlock:^(QBResponse *response) {
                     
}];

🚧

All retrieved chat messages will be marked as read after the request. If you decide not to mark chat messages as read, then add the following parameter to your extendedRequest -@{@"mark_as_read" : @"0"};

Filters

If you want to retrieve chat messages that were sent after or before a specific date-time only, you can use the filter. This is useful if you implement pagination for loading messages in your app.

You can apply filters for the following fields:

  • _id (string)
  • message (string)
  • date_sent (timestamp)
  • sender_id (integer)
  • recipient_id (integer)
  • attachments.type (string)
  • updated_at (date)

You can apply sort for the following fields:

  • date_sent

Filter

Applicable to types

Description

{field_name}

All types

Search records with the field which contains the specified value.

{field_name}[{search_operator}]

All types

Search a record with the field which contains the value according to the specified value and operator.

sort_asc

All types

Search results will be sorted by the specified field in ascending order.

sort_desc

All types

Search results will be sorted by the specified field in descending order.

skip

Integer

Skip N records in search results. Useful for pagination. Default (if not specified): 0.

limit

Integer

Limit search results to N records. Useful for pagination. Default value: 100. If limit is equal to 1, only the last record will be returned.

count

Integer

Count search results. Response will contain only count of records found.

Search operators

Here are the search operators that you can use to retrieve messages.

Search operators

Applicable to types

Description

lt

Integer, Float

Less Than operator.

lte

Integer, Float

Less Than or Equal to operator.

gt

Integer, Float

Greater Than operator.

gte

Integer, Float

Greater Than or Equal to operator.

ne

Integer, Float, String, Boolean

Not Equal to operator.

in

Integer, Float, String

IN array operator.

nin

Integer, Float, String

Not IN array operator.

all

Array

ALL are contained in array.

or

Integer, Float, String

All records that contain a value 1 or value 2.

ctn

String

All records that contain a particular substring.

Send/Receive chat messages

1-1 dialog

To send a message to 1-1 dialog use the code snippet below.

let message = QBChatMessage()
message.text = "How are you today?"
message.customParameters["save_to_history"] = true
    
let privateDialog = ...
privateDialog.send(message) { (error) in
    
}
QBChatMessage *message = [[QBChatMessage alloc] init];
message.text = @"How are you today?";
message.customParameters[@"save_to_history"] = @"1";
    
QBChatDialog *privateDialog = ...;
[privateDialog sendMessage:message completionBlock:^(NSError * _Nullable error) {
    
}];

📘

Make sure to set the save_to_history as true to save the message on the server. If the save_to_history is set as false, the message won't be saved on the server.

Group/public dialog

Join group/public dialog

Before you start chatting in a group/public dialog, you need to join it by calling join() method.

let groupDialog = ...
groupDialog.join { (error) in
    
}
QBChatDialog *groupDialog = ...;
[groupDialog joinWithCompletionBlock:^(NSError * _Nullable error) {
    
}];

Then you are able to send/receive messages.

let message = QBChatMessage()
message.text = "How are you today?"
message.customParameters["save_to_history"] = true
    
let groupDialog = ...
groupDialog.send(message) { (error) in
    
}
    
//MARK: ChatDelegate   
func chatDidReceive(_ message: QBChatMessage) {
    
}
QBChatMessage *message = [[QBChatMessage alloc] init];
message.text = @"How are you today?";
message.customParameters[@"save_to_history"] = @"1";
    
QBChatDialog *groupDialog = ...;
[groupDialog sendMessage:message completionBlock:^(NSError * _Nullable error) {
    
}];
    
//MARK: QBChatDelegate
- (void)chatDidReceiveMessage:(QBChatMessage *)message {
    
}

📘

Make sure to set the save_to_history as true to save the message on the server. If the save_to_history is set as false, the message won't be saved on the server.

Leave group/public dialog

You can leave the group/public dialog by calling groupDialog.leave() method.

let groupDialog = ...
groupDialog.leave { (error) in
    
}
QBChatDialog *groupDialog = ...;
[groupDialog leaveWithCompletionBlock:^(NSError * _Nullable error) {
    
}];

Unread messages count

To get a number unread messages in a particular dialog, use the code snippet below.

let unreadMessagesCount = dialog.unreadMessagesCount
NSUInteger unreadMessagesCount = chatDialog.unreadMessagesCount;

You can also retrieve the total number of unread messages using the totalUnreadMessageCountForDialogs() method . It returns the total count of unread messages for all dialogs of the user in totalUnreadCount. It also returns unread messages count for dialogs with IDs in dialogsDictionary if any dialogIDs are specified.

let dialogIDs: Set<String> = ["8b23aa4f5d0b0be0900041aa", "1c23aa4f5d0b0be0900041ad"]
QBRequest.totalUnreadMessageCountForDialogs(withIDs: dialogIDs, successBlock: { ( response, totalUnreadCount, dialogsDictionary) in
    
}, errorBlock: { (response) in
    
})
[QBRequest totalUnreadMessageCountForDialogsWithIDs:[NSSet setWithArray:@[@"8b23aa4f5d0b0be0900041aa", @"1c23aa4f5d0b0be0900041ad"]]
successBlock:^(QBResponse * _Nonnull response, NSUInteger count, NSDictionary<NSString *,id> * _Nonnull dialogs) {
    
} errorBlock:^(QBResponse * _Nonnull response) {
    
}];

Parameters

Description

dialogIDs

IDs of dialogs.

  • If dialogIDs are not specified, the total number of unread messages for all dialogs of the user will be returned.
  • If dialogIDs are specified, the total number of unread messages for the specified dialogs will be returned. Also, the total number of unread messages for all dialogs of the user will be returned.

Ping user

QuickBlox SDK can send application-level pings to a user. As a result, you can check if the user is connected to the Chat server.

let userId = 221809
let timeout = 20.0
QBChat.instance.pingUser(withID: userId, timeout: timeout) { (timeInterval, success) in
    // time interval of ping and whether it was successful
}
NSUInteger userId = 221809;
NSTimeInterval timeout = 20.0;
[QBChat.instance pingUserWithID:userId timeout:timeout completion:^(NSTimeInterval timeInterval, BOOL success) {
    // time interval of ping and whether it was successful
}];

Parameters

Required

Description

userId

yes

ID of the user.

timeout

no

Ping timeout. To control how much time it takes to respond to a ping, you should set a ping timeout. If the response wasn't received within the specified time frame, then the error callback is called. Default: 30 seconds.

As a result, a completion block with timeInterval and success parameters is called.

Parameters

Required

Description

timeInterval

yes

A double parameter. Indicates how long it took to ping in seconds.

success

yes

A boolean parameter. Indicates whether the ping was successful. If the sucess=1, the ping is successful (the user is connected to the Chat). If sucess=0, the ping isn't successful.

Ping server

QuickBlox SDK can send application-level pings to a server. As a result, you can check if there is a connection with the Chat server.

let timeout = 20.0
QBChat.instance.pingServer(withTimeout: timeout) { (timeInterval, success) in
    // time interval of ping and whether it was successful
}
NSTimeInterval timeout = 20.0;
[QBChat.instance pingServerWithTimeout:timeout completion:^(NSTimeInterval timeInterval, BOOL success) {
    // time interval of ping and whether it was successful
}];

Parameters

Required

Description

timeout

no

Ping timeout. To control how much time it takes to respond to a ping, you should set a ping timeout. If the response wasn't received within the specified time frame, then the error callback is called. Default: 30 seconds.

As a result, a completion block with timeInterval and success parameters is called.

Parameters

Required

Description

timeInterval

yes

A double parameter. Indicates how long it took to ping in seconds.

success

yes

A boolean parameter. Indicates whether the ping was successful. If the sucess=1, the ping was successful. If sucess=0, the ping wasn't successful.

Updated 18 days ago


What's Next

Advanced

Chat


Learn how to enable chat functionality for your app.

Suggested Edits are limited on API Reference Pages

You can only suggest edits to Markdown body content, but not to the API spec.