IM messages are classified by message destination into two types: one-to-one messages (also called C2C messages) and group messages.
Message Type | API Keyword | Description |
---|---|---|
One-to-one message | C2CMessage | Also called C2C message. When sending a one-to-one message, you must specify the UserID of the message recipient, and only the recipient can receive this message. |
Group message | GroupMessage | When sending a group message, you must specify the groupID of the target group, and all users in this group can receive this message. |
IM messages can also be classified by content into text messages, custom (signaling) messages, image messages, video messages, voice messages, file messages, location messages, combined messages, and group tips.
Message Type | API Keyword | Description |
---|---|---|
Custom message | CustomElem | It is a section of binary buffer and often used to transfer custom signaling in your application. |
Image message | ImageElem | When the IM SDK sends an original image, it automatically generates two images in different sizes. The three images are called the original image, large image, and thumbnail. |
Video message | VideoElem | A video message contains a video file and an image. |
Voice message | SoundElem | It supports displaying a red dot upon playback of the voice message. |
File message | FileElem | A file message cannot exceed 100 MB. |
Location message | LocationElem | A location message contains three fields: location description, longitude, and latitude. |
Combined message | MergerElem | Up to 300 messages can be combined. |
Group tip | GroupTipsElem | A group tip is often used to carry a system notification in a group, such as a notification indicating the following: a member joins or leaves the group; the group description is modified; or the profile of a group member is changed. |
V2TIMManager.h provides a set of simple APIs for sending and receiving messages. Although these APIs can only be used to send or receive text messages and custom (signaling) messages, they are easy to use and it takes only a few minutes to complete interfacing.
To send text messages, call sendC2CTextMessage or sendGroupTextMessage.
To send one-to-one custom (signaling) messages, call sendC2CCustomMessage or sendGroupCustomMessage. A custom message is essentially a section of binary buffer, and is often used to transfer custom signaling in your application.
To listen to simple text and signaling messages, call addSimpleMsgListener. To listen to image, video, and voice messages, call addAdvancedMsgListener defined in V2TIMManager + Message.h.
Note:Do not use addSimpleMsgListener together with addAdvancedMsgListener; otherwise, logic bugs may occur.
In the livestreaming scenario, it is a common way of communication to send or receive on-screen comments in an audio-video group. This can be easily implemented through the simple message APIs.
"FlyHeart" is an instruction. To configure the "FlyHeart" feature for a live room, perform the steps below:
{ "command": "favor", "value": 101 }
.Image, video, voice, file, and location messages are called rich media messages. Compared with sending or receiving simple messages, it is more complex to send or receive rich media messages.
create
function to create an object V2TIMMessage. Then, call the corresponding send
API to send this message.elemType
and perform secondary parsing on Elem
obtained based on elemType
.The following takes an image message as an example to describe the process of sending a rich media message.
elemType
in V2TIMMessage, and performs secondary parsing based on the message type to obtain the content of Elem
in the message.The sender creates and sends an image message.
// Obtain the local image path
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"png"];
// Create an image message
V2TIMMessage *msg = [[V2TIMManager sharedInstance] createImageMessage:imagePath];
// Send the image message
[[V2TIMManager sharedInstance] sendMessage:msg receiver:@"userA" groupID:nil
priority:V2TIM_PRIORITY_DEFAULT
onlineUserOnly:NO offlinePushInfo:nil progress:^(uint32_t progress) {
// Image upload progress (0-100)
} succ:^{
// The image message was sent successfully
} fail:^(int code, NSString *msg) {
// The image message failed to be sent
}];
The recipient identifies the image message, and parses the message to obtain the original image, large image, and thumbnail contained in the message.
- (void)onRecvNewMessage:(V2TIMMessage *)msg {
if (msg.elemType == V2TIM_ELEM_TYPE_IMAGE) {
V2TIMImageElem *imageElem = msg.imageElem;
// An image message contains an image in three different sizes: original image, large image, and thumbnail. The SDK automatically generates a large image and a thumbnail.
// A large image is obtained after the original image is proportionally compressed. After the compression, the smaller one of the height and width is equal to 720 pixels.
// A thumbnail is obtained after the original image is proportionally compressed. After the compression, the smaller one of the height and width is equal to 198 pixels.
NSArray<V2TIMImage *> *imageList = imageElem.imageList;
for (V2TIMImage *timImage in imageList) {
NSString *uuid = timImage.uuid; // Image ID
V2TIMImageType type = timImage.type; // Image type
int size = timImage.size; // Image size (bytes)
int width = timImage.width; // Image width
int height = timImage.height; // Image height
// Set the image download path `imagePath`. Here, `uuid` can be used as an identifier to avoid repeated download.
NSString *imagePath = [NSTemporaryDirectory() stringByAppendingPathComponent:
[NSString stringWithFormat: @"testImage%@",timImage.uuid]];
if (![[NSFileManager defaultManager] fileExistsAtPath:imagePath]) {
[timImage downloadImage:imagePath
progress:^(NSInteger curSize, NSInteger totalSize) {
NSLog(@"Image download progress: curSize: %lu,totalSize:%lu",curSize,totalSize);
} succ:^{
NSLog(@"Image download completed");
} fail:^(int code, NSString *msg) {
NSLog(@"Image download failed: code: %d,msg:%@",code,msg);
}];
} else {
// The image already exists
}
}
}
}
Note:For more information on the message parsing sample code, see FAQs > 5. How can I parse different types of messages.
For a group @ message, the sender can listen to the input of the @ character in the input box and call the group member selection interface. After selection is completed, the input box displays the content in the format of "@A @B @C......"
, and then the sender can continue to edit the message content and send the message. On the group chat list of the recipient’s conversation interface, the identifier "someone@me"
or "@all members"
will be displayed to remind the user that the user was mentioned by someone in the group.
Note:Currently, only text @ messages are supported.
// Obtain the ID data of the @ group member
TUITextMessageCellData *text = (TUITextMessageCellData *)data;
NSMutableArray<NSString *> *atUserList = text.atUserList;
// Create a group @ message
V2TIMMessage *atMsg = [[V2TIMManager sharedInstance] createTextAtMessage:text.content atUserList:atUserList];
// Send the group @ message
[[V2TIMManager sharedInstance] sendMessage:atMsg
receiver:nil
groupID:@"toGroupId"
priority:V2TIM_PRIORITY_DEFAULT
onlineUserOnly:NO
offlinePushInfo:nil
progress:nil
succ:^{
NSLog(@"group @ message is sent successfully");
}
fail:^(int code, NSString *desc) {
NSLog(@"group @ message failed to be sent");
}];
// Obtain the group @ data list
NSArray<V2TIMGroupAtInfo *> *atInfoList = conversation.groupAtInfolist;
// Parse the @ type (@me, @all members, @me and @all members)
BOOL atMe = NO; // Whether it's @me
BOOL atAll = NO; // Whether it's @all members
NSString *atTipsStr = @"";
for (V2TIMGroupAtInfo *atInfo in atInfoList) {
switch (atInfo.atType) {
case V2TIM_AT_ME:
atMe = YES;
break;
case V2TIM_AT_ALL:
atAll = YES;
break;
case V2TIM_AT_ALL_AT_ME:
atMe = YES;
atAll = YES;
break;
default:
break;
}
}
// Based on the @ type, prompt:
if (atMe && !atAll) {
atTipsStr = @"[someone@me]";
}
if (!atMe && atAll) {
atTipsStr = @"[@all members]";
}
if (atMe && atAll) {
atTipsStr = @"[someone@me][@all members]";
}
To implement the Combine and Forward feature similar to that in WeChat, it is necessary to create a combined message according to the original message list, and then send the combined message to the peer end. After the peer end receives the combined message, it will parse out the original message list. A title and abstracts are required to display the combined message.
Chat History of Vinson and Lynx | Title |
---|---|
Vinson: When is the new version of SDK scheduled to go online? | abstract1 |
Lynx: Next Monday. The specific time depends on the system test result in these two days. | abstract2 |
Vinson: OK | abstract3 |
The chat UI will display only the title and abstract information of the combined message, and the combined message list will be displayed only when the user clicks the combined message. To create a combined message, it is necessary to set not only the combined message list, but also the title and abstract information. The implementation process is as follows:
Note:Only available in Enhanced Edition v5.2.210 or later.
// List of messages to be forwarded, which can contain combined messages but not group tips
NSArray *msgs = @[message1,message2...];
// Title of the combined message
NSString *title = @"Chat History of Vinson and Lynx";
// Abstract list of the combined message
NSArray *abstactList = @[@"abstract1",@"abstract2",@"abstract3"];
// Combined messages are compatible with text. If SDKs of early versions do not support combined messages, the user will receive a text message with the content `compatibleText`.
NSString *compatibleText = @"Please upgrade to the latest version to check the combined message";
// Create a combined message
V2TIMMessage *mergeMessage = [[V2TIMManager sharedInstance] createMergerMessage:msgs title:title
abstractList:abstactList compatibleText:compatibleText];
// Send the combined message to the user Denny
[[V2TIMManager sharedInstance] sendMessage:mergeMessage receiver:@"denny" groupID:nil
priority:V2TIM_PRIORITY_NORMAL onlineUserOnly:NO offlinePushInfo:nil progress:nil succ:nil fail:nil];
- (void)onRecvNewMessage:(V2TIMMessage *)msg {
if (msg.elemType == V2TIM_ELEM_TYPE_MERGER) {
// Get the combined message elements
V2TIMMergerElem *mergerElem = msg.mergerElem;
// Get the title
NSString *title = mergerElem.title;
// Get the abstract list
NSArray *abstractList = mergerElem.abstractList;
// Download the combined message list when the user clicks the combined message
[msg.mergerElem downloadMergerMessage:^(NSArray<V2TIMMessage *> *msgs) {
// Download succeeded. `msgs` is the combined message list
for (V2TIMMessage *subMsg in msgs) {
// If the combined message list still contains combined messages, you can continue parsing
if (subMsg.elemType == V2TIM_ELEM_TYPE_MERGER) {
V2TIMMergerElem *mergerElem = subMsg.mergerElem;
// Get the title
NSString *title = mergerElem.title;
// Get the abstract list
NSArray *abstractList = mergerElem.abstractList;
// Download the combined message list when the user clicks the combined message
[msg.mergerElem downloadMergerMessage:nil fail:nil];
}
}
} fail:^(int code, NSString *desc) {
// Download failed
}];
}
}
When sending a group message, you can set whether a message requires a read receipt. If yes, the receiver can send a read receipt only after the message is read.
Note:
After creating a message, the sender specifies that the message requires a read receipt by using the needReadReceipt field of the message object V2TIMMessage, and sends the message to the group.
/// API call example
V2TIMMessage *message = [[V2TIMManager sharedInstance] createTextMessage:@"Group message read receipt"];
// Specify that the message requires a read receipt
message.needReadReceipt = YES;
// Send the message
[[V2TIMManager sharedInstance] sendMessage:message receiver:nil groupID:@"groupA" priority:V2TIM_PRIORITY_NORMAL onlineUserOnly:NO offlinePushInfo:nil progress:nil succ:nil fail:nil];
When receiving a message, the receiver determines whether the message requires a read receipt by using the needReadReceipt field of the message object V2TIMMessage. If a read receipt is required, and the user has read the message, the receiver calls the sendMessageReadReceipts API to send the message read receipt.
/// API call example
/// Assume that the message is read by user
if (!msg.isSelf && msg.needReadReceipt) {
[[V2TIMManager sharedInstance] sendMessageReadReceipts:@[msg] succ:^{
// Message read receipt sent successfully
} fail:^(int code, NSString *desc) {
// Failed to send the message read receipt
}];
}
After the receiver sends a message read receipt, the sender can use the onRecvMessageReadReceipts callback of V2TIMAdvancedMsgListener to listen for the notifications of group message read receipts.
/// API call example
[[V2TIMManager sharedInstance] addAdvancedMsgListener:self];
- (void)onRecvMessageReadReceipts:(NSArray<V2TIMGroupMessageReceipt *> *)receiptList {
for(V2TIMMessageReceipt *receipt in receiptList) {
// Unique ID of the message
NSString *msgID = receipt.msgID;
// Latest message read count
uint64_t readCount = receipt.readCount;
// Latest message unread count
uint64_t unreadCount = receipt.unreadCount;
}
}
When the sender enters the message list UI from other UIs, it pulls the message history first and then call the getMessageReadReceipts API to pull message read receipt information.
/// API call example
[[V2TIMManager sharedInstance] getGroupHistoryMessageList:@"groupA" count:20 lastMsg:nil succ:^(NSArray<V2TIMMessage *> *msgs) {
NSMutableArray *receiptMsgs = [NSMutableArray array];
// If the message is sent by you and it requires a read receipt, the message read receipt information needs to be pulled.
for (V2TIMMessage *msg in msgs) {
if (msg.isSelf && msg.needReadReceipt) {
[receiptMsgs addObject:msg];
}
}
[[V2TIMManager sharedInstance] getMessageReadReceipts:receiptMsgs succ:^(NSArray<V2TIMMessageReceipt *> *receiptList) {
NSMutableDictionary *param = [NSMutableDictionary dictionary];
for (V2TIMMessageReceipt *receipt in receiptList) {
[param setObject:receipt forKey:receipt.msgID];
}
for (V2TIMMessage *msg in msgs) {
V2TIMMessageReceipt *receipt = param[msg.msgID];
// Message read count. If `readCount` is `0`, no one has read the message.
uint64_t readCount = receipt.readCount;
// Message unread count. If `unreadCount` is `0`, all members have read the message.
uint64_t unreadCount = receipt.unreadCount;
}
} fail:^(int code, NSString *desc) {
// Failed to pull the message read status
}];
} fail:^(int code, NSString *desc) {
// Failed to pull the message
}];
The sender can call the getGroupMessageReadMemberList API to pull the list of members who have read a group message in pagination mode.
/// API call example
[[V2TIMManager sharedInstance] getGroupMessageReadMemberList:message filter:V2TIM_GROUP_MESSAGE_READ_MEMBERS_FILTER_READ nextSeq:0 count:100 succ:^(NSMutableArray<V2TIMGroupMemberInfo *> *members, uint64_t nextSeq, BOOL isFinished) {
// `members` is the list of members who have read the message pulled for the current page
// `nextSeq` indicates the cursor position for the next page pulling
// `isFinished` indicates whether the read member list has been fully pulled
// If the read member list is not fully pulled, continue with the next pulling (here is only the sample code. In pagination pulling mode, the action is recommended to be triggered by UI clicking by user).
if (!isFinished) {
[[V2TIMManager sharedInstance] getGroupMessageReadMemberList:message filter:V2TIM_GROUP_MESSAGE_READ_MEMBERS_FILTER_READ nextSeq:nextSeq count:100 succ:^(NSMutableArray<V2TIMGroupMemberInfo *> *members, uint64_t nextSeq, BOOL isFinished) {
// The read member list is pulled successfully
} fail:^(int code, NSString *desc) {
// Failed to pull the read member list
}];
}
} fail:^(int code, NSString *desc) {
// Failed to pull the read member list
}];
Currently, the one-to-one chat scenario does not support read receipts at the message level. In the scenario, when the receiver calls the markC2CMessageAsRead API to mark the conversation as read, and the sender will receive a read receipt, indicating that the peer has read the conversation. The read receipt carries the conversation read time of the receiver, and the sender can consider that all messages before this time are read by the peer.
// Mark messages coming from Haven as read
[[V2TIMManager sharedInstance] markC2CMessageAsRead:@"haven" succ:^{
} fail:^(int code, NSString *msg) {
}];
The event notification of the conversation read receipt is located in the advanced message listener V2TIMAdvancedMsgListener. To perceive the event, the sender must call addAdvancedMsgListener to set the listener. Then, the sender can perceive the event through the onRecvC2CReadReceipt callback.
- (void)onRecvC2CReadReceipt:(NSArray<V2TIMMessageReceipt *> *)receiptList {
// The sender may receive multiple read receipts at a time. Therefore, the array callback mode is used here.
for (V2TIMMessageReceipt *receipt in receiptList) {
// Message recipient
NSString * receiver = receipt.userID;
// Time of the read receipt. A message is considered as read if the timestamp in the chat window is not later than `timestamp` here.
time_t timestamp = receipt.timestamp;
}
}
@end
Normally, when you send one-to-one chat messages and group messages, the messages are included in the unread count (you can get the unread message count of a conversation via the unreadCount API of the V2TIMConversation conversation object). If you need to send messages that are excluded from the unread count, such as tips and control messages, send them as follows:
Note:Only available in Enhanced Edition v5.3.425 or later.
// Create the message object
V2TIMMessage *message = [[V2TIMManager sharedInstance] createTextMessage:@"This is a signaling message"];
// Set the identifier for excluding from the unread message count
message.isExcludedFromUnreadCount = YES;
// Send the message
[[V2TIMManager sharedInstance] sendMessage:msg receiver:@"userA" groupID:nil
priority:V2TIM_PRIORITY_DEFAULT onlineUserOnly:YES offlinePushInfo:nil progress:^(uint32_t progress) {
} succ:^{
// The message was successfully sent
} fail:^(int code, NSString *msg) {
// The message failed to be sent
}];
In certain scenarios, if you need to send messages that are excluded from lastMsg
of a conversation, send them as follows:
Note:Only available in Enhanced Edition v5.4.666 or later.
// Create the message object
V2TIMMessage *message = [V2TIMManager.sharedInstance createTextMessage:content];
// Set the identifier for excluding from lastMsg of the conversation
message.isExcludedFromLastMessage = YES;
// Send the message
[V2TIMManager.sharedInstance sendMessage:message receiver:@"userA" groupID:nil priority:V2TIM_PRIORITY_NORMAL onlineUserOnly:NO offlinePushInfo:nil progress:^(uint32_t progress) {
// Sending progress
} succ:^{
// The message was successfully sent
} fail:^(int code, NSString *desc) {
// The message failed to be sent
}];
A targeted group message is a message sent only to specified members in a group. You can send it as follows:
// Create an original message object
V2TIMMessage *message = [[V2TIMManager sharedInstance] createTextMessage:@"This is a targeted group message"];
// Create a targeted group message object, and specify the recipients "Vinson" and "Denny"
NSMutableArray *receiverList = [NSMutableArray array];
[receiverList addObject:@"vinson"];
[receiverList addObject:@"denny"];
V2TIMMessage *targetGroupMessage = [V2TIMManager.sharedInstance createTargetedGroupMessage:message receiverList:receiverList];
// Send the targeted group message in groupA
[[V2TIMManager sharedInstance] sendMessage:targetGroupMessage receiver:nil groupID:@"groupA"
priority:V2TIM_PRIORITY_DEFAULT onlineUserOnly:NO offlinePushInfo:nil progress:^(uint32_t progress) {
} succ:^{
// The message was successfully sent
} fail:^(int code, NSString *msg) {
// The message failed to be sent
}];
Note:
Only available in Enhanced Edition v6.0.1975 or later.
- This feature requires the Flagship Edition package.
- The original message object for creating a targeted group message cannot be a group @ message.
- The targeted group message feature is not available for Community and AVChatRoom groups.
- By default, targeted group messages are excluded from the unread count of the group conversation.
When the recipient's app is killed or when the recipient switches to the backend, the IM SDK cannot receive new messages through the normal network connection. In this scenario, the APNs service provided by Apple must be used to notify the recipient of new messages. For more information, see Offline Push (iOS).
When sending messages, you can use the offlinePushInfo field in the sendMessage API to set the title and voice for APNs offline push.
// Create and send an image message to groupA, and customize the title and voice for offline push.
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"png"];
// Create an image message
V2TIMMessage *msg = [[V2TIMManager sharedInstance] createImageMessage:imagePath];
V2TIMOfflinePushInfo *pushInfo = [[V2TIMOfflinePushInfo alloc] init];
// Customize the title and voice for offline push. `01.caf` is a sample file, which must be linked to the Xcode project. Here, you only need to enter the file name with the extension.
pushInfo.title = @"Customize the title displayed";
pushInfo.iOSSound = @"01.caf";
[[V2TIMManager sharedInstance] sendMessage:msg receiver:nil groupID:@"groupA" priority:V2TIM_PRIORITY_DEFAULT
onlineUserOnly:NO offlinePushInfo:pushInfo progress:^(uint32_t progress) {
} succ:^{
// The message was successfully sent
} fail:^(int code, NSString *msg) {
// The message failed to be sent
}];
To implement this feature, the sender needs to set the extended field ext
of the offline push object offlinePushInfo
, when sending a message. When the recipient opens the app, the recipient can obtain ext
through the didReceiveRemoteNotification
system callback, and then go to the corresponding chat window based on the content of ext
.
The following example assumes that Denny sends a message to Vinson.
ext
before sending a message.// Denny sets `offlinePushInfo` and specifies `ext` before sending a message
V2TIMMessage *msg = [[V2TIMManager sharedInstance] createTextMessage:@"Text message"];
V2TIMOfflinePushInfo *info = [[V2TIMOfflinePushInfo alloc] init];
info.ext = @"jump to denny";
[[V2TIMManager sharedInstance] sendMessage:msg receiver:@"vinson" groupID:nil priority:V2TIM_PRIORITY_DEFAULT
onlineUserOnly:NO offlinePushInfo:info progress:^(uint32_t progress) {
} succ:^{
} fail:^(int code, NSString *msg) {
}];
// Vinson receives the following callback after starting the app.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
// Parse `desc`, which is the extended field for online push.
if ([userInfo[@"ext"] isEqualToString:@"jump to denny"]) {
// Go to the chat window with Denny.
}
}
In some scenarios, you may wish that sent messages can only be received by online users or that a recipient is not aware of the message when the recipient is offline. For this purpose, you can set
Set onlineUserOnly
to YES
when calling sendMessage. After the setting, the sent messages differ from common messages in the following ways:
Typical example: displaying "The other party is typing..."
In the one-to-one chat scenario, you can call sendMessage to send the "I am typing..." message. When the recipient receives this message, "The other party is typing..." is displayed on the UI. The sample code is as follows:
// Send the "I am typing..." message to userA
NSString *customStr = @"{\"command\": \"textInput\"}";
NSData *customData = [customStr dataUsingEncoding:NSUTF8StringEncoding];
V2TIMMessage *msg = [[V2TIMManager sharedInstance] createCustomMessage:customData];
[[V2TIMManager sharedInstance] sendMessage:msg receiver:@"userA" groupID:nil
priority:V2TIM_PRIORITY_DEFAULT onlineUserOnly:YES offlinePushInfo:nil progress:^(uint32_t progress) {
} succ:^{
// The message was successfully sent
} fail:^(int code, NSString *msg) {
// The message failed to be sent
}];
The SDK supports the following types of message receiving options:
You can call the setC2CReceiveMessageOpt API to set the Mute Notifications option for one-to-one messages and call the setGroupReceiveMessageOpt API to set the Mute Notifications option for group messages.
Note:Only available in Enhanced Edition v5.3.425 or later.
The sender can call the revokeMessage API to recall a successfully sent message. By default, the sender can recall a message that is sent within 2 minutes. You can change the time limit for message recall. For detailed operations, see Message recall settings.
Message recall requires cooperation of the UI code at the recipient side. When the sender recalls a message, the recipient will receive a message recall notification, onRecvMessageRevoked. This notification contains the msgID
of the recalled message. Based on this msgID
, you can identify the message that has been recalled and change the corresponding message bubble to the "Message recalled" state on the UI.
[[V2TIMManager sharedInstance] revokeMessage:msg succ:^{
// The message was successfully recalled
} fail:^(int code, NSString *msg) {
// The message failed to be recalled
}];
- (void)onRecvMessageRevoked:(NSString *)msgID {
// msgList is the message list on the current chat interface
for(V2TIMMessage *msg in msgList){
if ([msg.msgID isEqualToString:msgID]) {
// `msg` is the recalled message. You need to change the corresponding message bubble state on the UI.
}
}
}
The recipient can call markC2CMessageAsRead or markGroupMessageAsRead, respectively, to mark incoming messages in a C2C conversation or a group conversation as read, and perform callback of onConversationChanged to notify the UI to update.
The recipient can call markAllMessageAsRead to quickly mark unread messages of all conversations as read, and perform callback of onConversationChanged to notify the UI to update.
Note:Only available in Enhanced Edition v5.8.1668 or later.
You can call getC2CHistoryMessageList to obtain historical messages of one-to-one chats, or call getGroupHistoryMessageList to obtain historical messages of group chats. If the network connection of the current device is normal, the IM SDK pulls historical messages from the server by default. If the network connection is unavailable, the IM SDK directly reads historical messages from the local database.
The IM SDK supports the feature of pulling historical messages by page. The number of messages pulled per page cannot be too large; otherwise, the pulling speed is affected. We recommend that you pull 20 messages per page.
The following example assumes that historical messages of groupA
are pulled by page, and the number of messages per page is 20. The sample code is as follows:
// The value `nil` of `lastMsg` is passed in for the first pulling, indicating that starting from the latest message, a total of 20 messages are pulled
[[V2TIMManager sharedInstance] getGroupHistoryMessageList:@"groupA" count:20
lastMsg:nil succ:^(NSArray<V2TIMMessage *> *msgs) {
// Messages that are pulled by page are listed from new to old by default
if (msgs.count > 0) {
// Obtain the start message for the next pulling by page
V2TIMMessage *lastMsg = msgs.lastObject;
// Pull the remaining 20 messages
[[V2TIMManager sharedInstance] getGroupHistoryMessageList:@"groupA" count:20
lastMsg:lastMsg succ:^(NSArray<V2TIMMessage *> *msgs) {
// Message pulling is completed
} fail:^(int code, NSString *msg) {
// Failed to pull the message
}];
}
} fail:^(int code, NSString *msg) {
// Failed to pull the message
}];
In actual scenarios, pulling by page is often triggered by your swipe operation. Each time when you swipe on the message list, pulling by page is triggered once. However, the principle is similar to the preceding sample code. In either case, lastMsg
specifies the start message for pulling, and count
specifies the number of messages pulled each time.
You can call the deleteMessages API to delete historical messages. After deletion, historical messages cannot be recovered.
By default, the IM SDK does not prevent message sending and receiving among strangers. If you wish that one-to-one messages can be sent or received only among friends, you can log in to the IM console, choose Feature Configuration > Login and Message > Relationship Check, and enable Check Relationship for One-to-One Messages. After this feature is enabled, you can send messages only to friends. When you try to send messages to strangers, the IM SDK returns the 20009 error code.
To avoid receiving messages from a specific user, you can blocklist the user or set the Mute Notifications option for messages from the user. After setting the Mute Notifications option, you can change the Mute Notifications status.
Adding a user to the blocklist:
Call the addToBlackList API to add the user to the blocklist. When the user is blocklisted, the user does not know that he/she is in the blocklist by default. That is, after this user sends a message, the prompt still indicates that the message is sent successfully, but in fact the recipient will not receive the message. If you want a user on the blocklist to know that his/her message fails to be sent, you can log in to the IM console, choose Feature Configuration > Login and Message > Blocklist Check, and disable Show "Sent successfully" After Sending Messages. After this feature is disabled, the IM SDK will return the 20007 error code when a user in the blocklist sends a message.
**Setting "Mute Notifications" for messages from a specified user: **
Call the setC2CReceiveMessageOpt API to set the message receiving option to V2TIM_NOT_RECEIVE_MESSAGE
.
Note:Only available in Enhanced Edition v5.3.425 or later.
For Enhanced Edition v5.3.425 or later, call the setGroupReceiveMessageOpt API to set the message receiving option to V2TIM_NOT_RECEIVE_MESSAGE
.
For SDKs of other versions, call the setReceiveMessageOpt
API to set the message receiving option to V2TIM_GROUP_NOT_RECEIVE_MESSAGE
.
In the one-to-one chat scenario, if the recipient calls markC2CMessageAsRead to mark a message as read, the read receipt received by the sender contains timestamp
. Based on timestamp
, the SDK determines whether the other party reads the message. Currently, timestamp
is stored locally, and will be lost when the app is reinstalled.
Elem
?You can call appendElem after creating a Message
object via the Elem
member of the Message
object to add the next Elem
member.
Below is an example of text message + custom message:
V2TIMMessage *msg = [[V2TIMManager sharedInstance] createTextMessage:@"text"];
V2TIMCustomElem *customElem = [[V2TIMCustomElem alloc] init];
customElem.data = [@"custom message" dataUsingEncoding:NSUTF8StringEncoding];
[msg.textElem appendElem:customElem];
Elem
objects?Message
object to parse the first Elem
object.Elem
object to obtain the next Elem
object. If the next Elem
object exists, the Elem
object instance is returned. Otherwise, nil
is returned.- (void)onRecvNewMessage:(V2TIMMessage *)msg {
// View the first Elem object
if (msg.elemType == V2TIM_ELEM_TYPE_TEXT) {
V2TIMTextElem *textElem = msg.textElem;
NSString *text = textElem.text;
NSLog(@"Text information: %@", text);
// Check whether `textElem` is followed by more `Elem` objects
V2TIMElem *elem = textElem.nextElem;
while (elem != nil) {
// Identify the `Elem` type
if ([elem isKindOfClass:[V2TIMCustomElem class]]) {
V2TIMCustomElem *customElem = (V2TIMCustomElem *)elem;
NSData *customData = customElem.data;
NSLog(@"Custom information: %@",customData);
}
// Continue to check whether the current Elem is followed by more Elem objects
elem = elem.nextElem;
}
// If `elem` is `nil`, all `Elem` objects have been parsed
}
}
It is complex to parse a message. We provide the sample code for parsing different types of messages. You can copy the code to your project, and perform secondary development based on your actual needs.
When you use a PNG image in an Xcode project to create an image message and send it, a sending failure message will be displayed. The reason is that Xcode compresses the PNG images in projects and modifies the file headers by default, and as a result, the images cannot be identified by IM. To solve the problem, configure your Xcode project as shown in the following figure.
Was this page helpful?