Add the event delegate to receive messages in real-time using the addDelegate() method. The event delegate enables the app to listen to message events associated with receiving a message, delivery receipts, and read receipts.
QBChat.instance.addDelegate(self)
QBChat.instance.addDelegate(self)
[QBChat.instance addDelegate: self];
You should also implement the QBChatDelegate methods in your chat controller to track events in your chat.
/// MARK: - QBChatDelegateextension YourViewController: QBChatDelegate { // MARK: - Manage chat receive message callback's func chatRoomDidReceive(_ message: QBChatMessage, fromDialogID dialogID: String) { // Called whenever group chat dialog did receive a message. // !!!note Will be called on both recipients' and senders' device (with corrected time from server) } func chatDidReceive(_ message: QBChatMessage) { // Called whenever new private message was received from QBChat. // !!!note Will be called only on recipient device }}
/// MARK: - QBChatDelegateextension YourViewController: QBChatDelegate { // MARK: - Manage chat receive message callback's func chatRoomDidReceive(_ message: QBChatMessage, fromDialogID dialogID: String) { // Called whenever group chat dialog did receive a message. // !!!note Will be called on both recipients' and senders' device (with corrected time from server) } func chatDidReceive(_ message: QBChatMessage) { // Called whenever new private message was received from QBChat. // !!!note Will be called only on recipient device }}
/// MARK: - QBChatDelegate// MARK: - Manage chat receive message callback's- (void)chatDidReceiveMessage:(QBChatMessage *)message { // Called whenever new private message was received from QBChat. // !!!note Will be called only on recipient device}- (void)chatRoomDidReceiveMessage:(QBChatMessage *)message fromDialogID (NSString*)dialogID { // Called whenever group chat dialog did receive a message. // !!!note Will be called on both recepients' and senders' device (with corrected time from server)}
To send a message to a group or public dialog, use the code snippet below.
You need to join the group and public dialog by calling the join() method before you start chatting in a dialog. Once the dialog is joined, you can receive/send messages. See this section to learn how to join the dialog.
let message = QBChatMessage()message.text = "How are you today?"message.customParameters["save_to_history"] = truelet groupDialog = ...groupDialog.send(message) { (error) in}//MARK: ChatDelegatefunc chatRoomDidReceive(_ message: QBChatMessage, fromDialogID dialogID: String) { }
let message = QBChatMessage()message.text = "How are you today?"message.customParameters["save_to_history"] = truelet groupDialog = ...groupDialog.send(message) { (error) in}//MARK: ChatDelegatefunc chatRoomDidReceive(_ message: QBChatMessage, fromDialogID dialogID: String) { }
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. However, the message will be delivered to the user in either case.
Chat attachments are supported by the content API. In order to send a chat attachment, you need to upload the file to QuickBlox cloud storage and obtain a link to the file (file UID). Then you need to include this UID into the chat message and send it.
let url = URL(fileURLWithPath:"file_path")//for imageQBRequest.uploadFile(with: url, fileName: fileName, contentType: "image/png", isPublic: true, successBlock: { (response, uploadedBlob) in let attachment = QBChatAttachment() attachment.id = uploadedBlob.uid attachment.name = uploadedBlob.name //for image attachment.type = "image" attachment.url = uploadedBlob.publicUrl() let message = QBChatMessage() message.text = "Image Attachment" //Set attachment message.attachments = [attachment] //Send message with attachment chatDialog.send(message, completionBlock: { (error) in })}, statusBlock: { (request, status) in //Update UI with upload progress}, errorBlock: { (response) in //show upload error})
let url = URL(fileURLWithPath:"file_path")//for imageQBRequest.uploadFile(with: url, fileName: fileName, contentType: "image/png", isPublic: true, successBlock: { (response, uploadedBlob) in let attachment = QBChatAttachment() attachment.id = uploadedBlob.uid attachment.name = uploadedBlob.name //for image attachment.type = "image" attachment.url = uploadedBlob.publicUrl() let message = QBChatMessage() message.text = "Image Attachment" //Set attachment message.attachments = [attachment] //Send message with attachment chatDialog.send(message, completionBlock: { (error) in })}, statusBlock: { (request, status) in //Update UI with upload progress}, errorBlock: { (response) in //show upload error})
The same flow is supported on the message receiver’s side. When you receive a message with an attachment, you need to get the file UID, and then download the file from the cloud storage.
func chatDidReceive(_ message: QBChatMessage) { if let attachment = message.attachments?.first, let uid = attachment.id { QBRequest.downloadFile(withUID: uid, successBlock: { (response, data) in //process file data }, statusBlock: { (response, status) in //Update UI with dowonload progress }, errorBlock: { (response) in //show download error }) }}
func chatDidReceive(_ message: QBChatMessage) { if let attachment = message.attachments?.first, let uid = attachment.id { QBRequest.downloadFile(withUID: uid, successBlock: { (response, data) in //process file data }, statusBlock: { (response, status) in //Update UI with dowonload progress }, errorBlock: { (response) in //show download error }) }}
You have an option to extend the message with additional fields. Specify one or more key-value items in the message. Using these items, you can implement the ability for a user to send self-location information to another user or notification messages signifying that a user has left a group, etc.
let message = QBChatMessage()message.text = "How are you today?"message.customParameters["save_to_history"] = "1"message.customParameters["customParam1"] = "book"message.customParameters["customParam2"] = "21"let dialog = ...dialog.send(message) { (error) in}
let message = QBChatMessage()message.text = "How are you today?"message.customParameters["save_to_history"] = "1"message.customParameters["customParam1"] = "book"message.customParameters["customParam2"] = "21"let dialog = ...dialog.send(message) { (error) in}
Extra data. Specify any key-value pairs. In each pair, the key and value are both string values. Set the save_to_history as 1 to save a message to the history.
Every dialog stores its chat history that you can retrieve using the messages(withDialogID:extendedRequest:) method. The request below will return messages for a specific dialog, sorted by the date_sent field in descending order, limited to 50 dialogs on the page.
If you want to mark all retrieved chat messages as a read, set the mark_as_read parameter as 1 in the extendedRequest. If you decide not to mark chat messages as read, just set the mark_as_read parameter as 0.
If you want to retrieve only messages updated after some specific date time and order the search results, you can apply operators. This is useful if you cache messages somehow and do not want to obtain the whole list of messages on every app start. Thus, you can apply search and sort operators to list messages on the page so that it is easier to view specific messages. The operators are set as key-value parameters in the extendedRequest dictionary.
If you want to get a paginated list of messages from the server, you can set the key-value parameters in the extendedRequest dictionary.
Pagination parameter
Description
skip
Skip N records in search results. Useful for pagination. Default (if not specified): 0.
limit
Limit search results to N records. Useful for pagination. Default value: 100.
Any user in the occupantIDs can delete a message from the dialog. As a result, the message will be deleted from the current user history, without affecting the histories of other users.
The owner of the dialog can completely remove messages from all users’ histories. This is achieved by setting the forAllUsers parameter to true.
The message is considered as sent if it has been delivered to the server. To get to know that a message has been delivered to the server, make sure to enable a stream management before connecting to the Chat server. See this section to learn how to enable the stream management.
Thus, you send a message to the server and if no error is returned, it is considered as sent (by default). There is no field for a sent status in the message model.
chatDialog.send(message) { (error) in if error == nil { // status - 'sent' }}
chatDialog.send(message) { (error) in if error == nil { // status - 'sent' }}
You should enable Stream Management before you do the login() because the Stream Management is initialized while Chat login is performed.
The Stream Management defines an extension for active management of a stream between a client and server, including features for stanza acknowledgments.
As a sender, you may want to be informed that a message has been successfully delivered to the recipient. The mark-as-delivered functionality allows to notify the sender about message delivery.
To track the event when the message has been delivered to the user, use the chatDidDeliverMessage(messageID:dialogID:) method of the QBChatDelegate delegate.
A message can be marked as delivered automatically by the server once a message is successfully delivered to the recipient. Set the markable as true using the send() method if you want, as a sender, to receive message delivery receipts from other recipients. Thus, the markable parameter enables the sender to request the delivery receipt. It also enables the recipient to confirm the message delivery. However, if markable is false or omitted, then you can notify a sender about the delivery receipt using the mark(asDelivered:) method.
let message = QBChatMessage()message.markable = truemessage.text = "How are you today?"chatDialog.send(message) { (error) in}
let message = QBChatMessage()message.markable = truemessage.text = "How are you today?"chatDialog.send(message) { (error) in}
QBChatMessage *message = [QBChatMessage new];message.markable = YES;message.text = @"How are you today?";[chatDialog sendMessage:message completionBlock:^(NSError * _Nullable error) {}];
Make sure to understand, that marking-as-delivered operation just confirms the fact of message delivery. The message acquires the delivered status when the message delivered event is received.
When a message is marked as delivered, the IDs of users who have received the message are stored in the message model, on the server. Thus, you can request a chat history from the server to get to know who received the message using the messages(withDialogID:) method. See this section to learn how to retrieve chat history.
You can also update the delivered_ids field in the message model, on the server, by using the method below. As a result, the ID of the user who has received the message will be added to the array of delivered_ids field. However, the server won’t notify the user about the change in the message model.
As a sender, you may want to be informed that a message has been read by the recipient. The mark-as-read functionality allows to notify the sender that a message has been read.
To track the event when the message has been read by the user, the chatDidReadMessage(messageID:dialogID:readerID:) method of the QBChatDelegate is used.
When a message is marked as read, the IDs of users who have read the message are stored in the message model, on the server. Thus, you can request a chat history from the server to get to know who read the message using the messages(withDialogID:) method. See this section to learn how to retrieve chat history.
You can also update the read_ids field in the message model, on the server, by using the method below. As a result, the ID of the user who has read the message will be added to the array of read_ids field. However, the server won’t notify the user about the change in the message model.
You may want, as a sender, to let the recipient know that you are typing the message or have stopped typing the message. Use typing indicators as a form of chat-specific presence. Typing indicators allow to indicate if users are typing messages in a dialog at the moment.
There are the following typing notifications supported.
typing. The user is composing a message. The user is actively interacting with a message input interface specific to this chat session (for example, by typing in the input area of a chat window).
stopped. The user had been composing but now has stopped. The user has been composing but has not interacted with the message input interface for a short period of time (for example, 30 seconds).
To track the event when the sender is typing the message, use the onUserIsTyping(userID:) method of the delegate.
To notify a recipient that a sender is typing the message, use the sendUserIsTyping() method. As a result, the server will notify a recipient about the event.
chatDialog.sendUserIsTyping()
chatDialog.sendUserIsTyping()
[chatDialog sendUserIsTyping];
To notify a recipient that a sender had been composing a message but now has stopped, use the sendUserStopTyping() method. As a result, the server will notify a recipient about the event.
There is a way to send system messages to other users about some events. For example, a system message can be sent when a user has joined or left a group dialog. System messages are handled over a separate channel and are not mixed up with regular chat messages. Thus, they are handled by chatDidReceiveSystemMessage() callback of QBChatDelegate. See this section to learn how to add QBChatDelegate.
System messages are also not shown in the dialog history and, consequently, are not stored on the server. This means that these messages will be delivered only to online users. Send system messages using the sendSystemMessage() method.
enum MessageType : String { case createGroupDialog = "1" case addUsersToGroupDialog = "2" case leaveGroupDialog = "3"}var message: QBChatMessage = QBChatMessage()let params = NSMutableDictionary()params["notification_type"] = MessageType.leaveGroupDialog.rawValueparams["dialog_id"] = "5356c64ab35c12bd3b108a41"message.customParameters = paramsmessage.recipientID = 344QBChat.instance.sendSystemMessage(message) { (error) in}#pragma mark -#pragma mark QBChatDelegatefunc chatDidReceiveSystemMessage(message: QBChatMessage!) {}
enum MessageType : String { case createGroupDialog = "1" case addUsersToGroupDialog = "2" case leaveGroupDialog = "3"}var message: QBChatMessage = QBChatMessage()let params = NSMutableDictionary()params["notification_type"] = MessageType.leaveGroupDialog.rawValueparams["dialog_id"] = "5356c64ab35c12bd3b108a41"message.customParameters = paramsmessage.recipientID = 344QBChat.instance.sendSystemMessage(message) { (error) in}#pragma mark -#pragma mark QBChatDelegatefunc chatDidReceiveSystemMessage(message: QBChatMessage!) {}