Instant Messaging
iOS
Getting Started
Product Introduction
Overview
Features
Feature overview
Account Integration and Login
Basic Message Features
Group Chat
Chat Room
Chat Room Tags
Multi-device Login
Statistics Monitoring
Limits
Development Integration
Message Sending
Message Receiving
Recent Chats
Server Sessions
User Profile
User Relationship
Online Status Subscription
System Notification
APNs
Superteam
Chat Room
Anti-spam
Chat Extension
Miscellaneous Features
Reference Documents
Configuration Instruction for PushKit
Push Configuration for Apple iOS
API References
iOS API Reference
Status Codes

Sending Messages

Update time: 2021/12/06 15:00:20

Overview

The structure which represents messages in the SDK is
NIMMessage. Message is the most critical class for CommsEase's instant messaging, and is the basic model for delivering messages. For information about message receiving, audio message processing, see Message Receiving.

List of some significant properties:

Parameter Type Description
messageType Message type Message type is enumerated and read-only. When constructing a message, the SDK will automatically determine and fill in the message type based on the messageObject.
messageSubType Message subtype 0 by default. This item should be set in customizing the message subtype. During local message retrieval, you can find the specified subtype by setting the messageSubTypes of NIMMessageSearchOption.
from Message sender Sender Id. When a message is sent, the SDK will automatically fill in Id based on the current login sate
session Message session ID for sending a message to the session. For P2P messaging, it is the recipient Id; for team or chat room messaging, it is the team or chat room Id.
messageId Client Id Unique message identification, automatically generated after the initialization of the message object
serverID Server Id Generated on the server after the message has been sent successfully
text Message text Text for UI display. In general, the text fields are nil instead of text and tip messages.
messageObject Message attachment For the property that the developer should focus on, the attachments should follow the NIMMessageObject protocol. The developer classified messages into different types by injecting different message attachments and attaching the information required for different types of messages, such as image data and location.
setting Message setting By injecting a message object before sending a message, the developer can customize various settings of the current message, such as message state and multi-client synchronization.
antiSpamOption Anti-spam option Currently it only supports CommsEase YiDun, so it can be set only when CommsEase GuideEase is connected.
apnsContent Push After APNS push is set, your phone will receive the Apple push notification in the background.
apnsPayload Message push Payload You can define the Message push Payload by this field, Apple's built-in field currently only supports the sound field
apnsContent Push After APNS push is set, your phone will receive the Apple push notification in the background.
apnsMemberOption Push option of specified member By injecting this object before sending a message, the developer can complete more complex push settings, such as forced push and partial push. Currently, it is only available in team sessions.
remoteExt Sever extension The client can set this field before sending a message, and it will be stored locally and sent to the opposite side. In the upper layer, please ensure that NSDictionary can be converted to JSON
localExt Client extension The client can set this field, and it will only be stored locally instead of being sent to the opposite side. In the upper layer, please ensure that NSDictionary can be converted to JSON. If a message has been sent, you should manually call the stored message to local.
messageExt Message extension field The message extension field sent by the server is not persisted locally and is currently only available for chat room messages (NIMMessageChat roomExtension).
timestamp Message sending time The position of locally stored messages in the session list can be adjusted by updating the timestamp, and then the message timestamp will be automatically corrected by the server.
isReceivedMsg Is message received based on the concept of roaming message, the message sent by yourself after Roaming messages are still a "received message", and this field is designed to determine whether the message should be sent or received again if an error is found.
deliveryState Message delivery state This field is only valid for sent messages.
attachmentDownloadState Message attachment download state This field is only valid for received messages.
isOutgoingMsg Is message outgoing Since you can send a message to yourself, not all messages from yourself are outgoing messages. This field is designed to determine the avatar position (left or right).
isPlayed Is the message played If you have updated this property, the SDK will automatically update the corresponding data in the DB.
isDeleted Is the message marked as deleted Deleted messages will only be marked as deleted when stored locally, and will be filtered out when you get a local message list; only APIs that fetch messages based on messageId may return deleted messages.
isRemoteRead Is the message read on the opposite side This field is only valid if the current message is a P2P message and isOutgoingMsg is YES, and The API of sending a read receipt should be called on the opposite side.
senderName Message sender name When you send a message to yourself, this value may be nil, and represents the current nickname of the sender, not the nickname used when the message is sent. This field is invalid for chat room messages.
senderClientType Sender client type The type of sender client may increase with SDK update, and the upper layer developer should consider whether the old and new versions are compatible.

It is recommended that the state properties of the above messages are only read and written in the main thread.

The following messages are currently available, and different types of messages correspond to different message objects:

Message type MessageObject
Text message nil
Image messages NIMImageObject
Audio message NIMAudioObject
Video message NIMVideoObject
File message NIMFileObject
Location message NIMLocationObject
Notification message NIMNotificationObject
Message notification NIMTipObject
Custom message NIMCustomObject

Send messages

The developer should send messages over the NIMChatManager protocols in NIMSDK.

Prototype

@protocol NIMChatManager <NSObject>
/**
 * Send a message
 *
 * @param message - Message
 * @param session - Acceptor session
 * @param error - Error. If an error occurs in the stage of preparing to send a message, the error will be filled with related information.
 *
 * @return - Callback that is returned after sending. The callback here only indicates that the function is invoked and a message shall be sent to complete the callback sendMessage:didCompleteWithError:. As a result, it can determine that the message has been sent to the server.
 */
- (BOOL)sendMessage:(NIMMessage *)message
          toSession:(NIMSession *)session
              error:(NSError * __nullable *)error;
@end

For specific information in NIMSession, please see "Recent Session".

In addition, the methods of asynchronously sending messages are available for large files.

@protocol NIMChatManager <NSObject>
/**
 * Asynchronously send a message. It is usually used for sending a large file.
 *
 * @param message - Message
 * @param session - Receiver
 * @param completion - Callback that is returned after sending. The callback here only indicates that the function is invoked and a message shall be sent to complete the callback sendMessage:didCompleteWithError:. As a result, it can determine that the message has been sent to the server.
 */
- (void)sendMessage:(NIMMessage *)message
          toSession:(NIMSession *)session
         completion:(nullable void(^)(NSError * __nullable error))completion;    
@end

Property List

Parameter Type Description
message NIMMessage After constructing a message, the developer should select the corresponding messageObject (text message can be filled in, and no message attachments are injected), and can feed the message into this API.
session NIMSession Session
error NSError * The developer should construct a NSError object and feed the object reference. If an error occurs at the stage of preparing for sending a message, this object will be populated with the appropriate information. A parameter error or login error generally occurs. You can illustrate and locate the specific error type based on the error code.
completion void(^)(NSError *error) If this callback is completed, it only means that The API has been successfully called.

The developer should monitor the message sending status over the NIMChatManagerDelegate protocol.

@protocol NIMChatManagerDelegate <NSObject>
/**
 * Callback that is returned after sending a message
 *
 * @param message - Message that is sent.
 * @param error - Failure reason. If it is successful, value of error is nil.
 */
- (void)sendMessage:(NIMMessage *)message 
  didCompleteWithError:(nullable NSError *)error; 
@end

In addition, the developer can get the progress of sending a message in the following callbacks:

@protocol NIMChatManagerDelegate <NSObject>
/**
 * A callback for the progress of sending a message
 *
 * @param message - Message that is sent.
 * @param progress - Progress
 */
- (void)sendMessage:(NIMMessage *)message 
           progress:(float)progress;
@end

Send text messages

Example of sending a text message hello to friend Id user:

// Construct detailed session: Peer-to-peer chat; account of the other party is user.
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Construct detailed message
NIMMessage *message = [[NIMMessage alloc] init];
message.text    = @"hello";
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

Send image messages

List of image attachment NIMImageObject parameters

Parameter Type Description
path NSString Local image path
thumbPath NSString Local thumb path: thumbs are automatically downloaded by SDK by default. If it is found that a thumb does not exist locally, you can manually call the method of fetching thumbs fetchMessageAttachment:error: over the NIMChatManager protocol before download
URL NSString Remote URL path for large images: the developer can download a large image by this property.
thumbURL NSString Remote thumb URL path is only suitable for resources uploaded using CommsEase, otherwise it is invalid
size NSString Image size
option NIMImageOption The image compression option is only valid when it is sent and initialized by initWithImage
fileLength NSString File size
MD5 NSString Image MD5

NIMImageOption parameter list

Parameter Type Description
compressQuality float The compression parameter is 0 by default, and 0.0 - 1.0 is acceptable. If the value is 0 or illegal, the image is compressed as per 0.5
format NIMImageFormat The image can be compressed by JPEG or PNG. By default, the format is JPEG.

Ordinary image attachments are initialized in three ways:

  • UIImage initialization
@interface NIMImageObject : NSObject<NIMMessageObject>
/**
 * Initialization method for image instance object
 *
 * @param image - Image to be sent
 *
 * @return - Image instance object
 */
- (instancetype)initWithImage:(UIImage*)image;

/**
* Initialization method for image instance object
*
* @param image - Image to be sent
* @param scene - Scene type
*
* @return - Image instance object
*/
- (instancetype)initWithImage:(UIImage*)image scene:(NSString *)scene;
@end

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get image attachment object
NIMImageObject *object = [[NIMImageObject alloc] initWithImage:image];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];
  • Image path initialization
@interface NIMImageObject : NSObject<NIMMessageObject>
/**
 * Initialization method for image instance object
 *
 * @param filepath - Image path to be sent
 *
 * @return - Image instance object
 */
 - (instancetype)initWithFilepath:(NSString *)filepath;
 
 /**
 * Initialization method for image instance object
 *
 * @param filepath - Image path to be sent
 * @param scene - Scene type
 *
 * @discussion - The original image without compressive transformation is uploaded with The API. iOS 11 Apple uses a new image format HEIC. If the original image may result in incompatibility with other devices, upper-level developers shall make compatible transformations for format.
 *
 * @return - Image instance object
 */
 - (instancetype)initWithFilepath:(NSString *)filepath scene:(NSString *)scene;
 @end

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get image attachment object
NIMImageObject *object = [[NIMImageObject alloc] initWithFilepath:path];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];
  • Image data initialization
@interface NIMImageObject : NSObject<NIMMessageObject>
  /**
   * Initialization method for image instance object
   *
   * @param data - Image data
   * @param extension - Recommended suffix name of image data
   *
   * @return - Image instance object
   */
- (instancetype)initWithData:(NSData *)data
                   extension:(NSString *)extension;
                   
/**
* Initialization method for image instance object
*
* @param data - Image data
* @param extension - Recommended suffix name of image data
* @param scene - Scene type
*
* @return - Image instance object
*/
- (instancetype)initWithData:(NSData *)data
                   extension:(NSString *)extension
                   scene:(NSString *)scene;
@end                    

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get image attachment object
NIMImageObject *object = [[NIMImageObject alloc] initWithData:data extension:@"png"];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

For Webp images, the image instance objects should be initialized in the following ways:

@interface NIMImageObject : NSObject<NIMMessageObject>
  /**
   * Initialization method for image instance object. It can be used for sending Webp image.
   * @param filepath - Image path to be sent
   * @param scene - Scene type
   * @param size - Image width and height. When Webp file is sent, the image size shall be input.
   * @return - Image instance object
   */
- (instancetype)initWithFilepath:(NSString *)
                  filepath scene:(NSString *)scene 
                            size:(CGSize)size
                   
/**
* Initialization method for image instance object. It can be used for sending Webp image.
* @param data - Image data
* @param extension - Recommended suffix name of image data
* @param scene - Scene type
* @param size - Image width and height. When Webp file is sent, the image size shall be input.
* @return - Image instance object
*/
- (instancetype)initWithData:(NSData *)data 
                   extension:(NSString *)extension 
                       scene:(NSString *)scene 
                        size:(CGSize)size
@end                    

Send audio message

Audio attachment NIMAudioObject parameter list

Parameter Type Description
path NSString Local audio path: audio is automatically downloaded by SDK by default. If it is found that an audio file does not exist locally, you can manually call the method fetchMessageAttachment:error:of fetching an audio attachment over NIMChatManager protocol.
URL NSString Remote audio URL path
duration NSInteger Audio duration. Unit: millisecond. The SDK will automatically parse the audio duration based on the incoming file information, and the developer can also calculate and set this value
MD5 NSString Audio MD5

The audio attachment is initialized in two ways:

  • Audio path initialization
@interface NIMAudioObject : NSObject<NIMMessageObject>
/**
 * Initialization method for audio attachment
 *
 * @param sourcePath - Audio path
 *
 * @return - Audio instance object
 */
 - (instancetype)initWithSourcePath:(NSString *)sourcePath;
 
 /**
 * Initialization method for audio instance object
 *
 * @param sourcePath - Audio path
 * @param scene - Scene type
 *
 * @return - Audio instance object
 */
 - (instancetype)initWithSourcePath:(NSString *)sourcePath scene:(NSString *)scene;
@end

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get audio attachment object
NIMAudioObject *object = [[NIMAudioObject alloc] initWithSourcePath:path];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];
  • Audio data initialization
@interface NIMAudioObject : NSObject<NIMMessageObject>
/**
* Initialization method for audio instance object
*
* @param data - Audio data
* @param extension - Pre-fix name of an audio data file
*
* @return - Audio instance object
*/ 
- (instancetype)initWithData:(NSData *)data
                extension:(NSString *)extension;
                
/**
* Initialization method for audio instance object
*
* @param data - Audio data
* @param extension - Pre-fix name of audio data file
* @param scene - Scene type
*
* @return - Audio instance object
*/
- (instancetype)initWithData:(NSData *)data
                   extension:(NSString *)extension
                       scene:(NSString *)scene;
@end

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get audio attachment object
NIMAudioObject *audioObject = [[NIMAudioObject alloc] initWithData:data extension:@"aac"];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

Sending a video message

Video attachment NIMVideoObject parameter list

Parameter Type Description
displayName NSString The video display name is defined by the developer and suitable for upper UI
MD5 NSString MD5 generated based on video data
path NSString Local video path
URL NSString Remote video path
coverURL NSString Remote path of video cover: only the videos uploaded to the CommsEase server support the cover address, otherwise the address will be invalid
coverPath NSString Local path of video cover. The video cover is automatically downloaded by SDK by default. If it is found that the cover file does not exist locally, you can manually call the method of fetching a cover fetchMessageAttachment:error: over the NIMChatManager protocol
coverSize CGSize The size of the video cover is calculated by SDK
duration NSInteger Video duration. Unit: millisecond. The SDK will automatically parse the duration based on the incoming file information, and the upper layer can also set this value.

The video message attachment is initialized in two ways:

  • Path initialization
@interface NIMVideoObject : NSObject<NIMMessageObject>
/**
 * Initialization method for video instance object
 *
 * @param sourcePath - File path of video
 *
 * @return - Video instance object
 */
- (instancetype)initWithSourcePath:(NSString *)sourcePath;

/**
* Initialization method for video instance object
*
* @param sourcePath - File path of video
* @param scene - Scene type
*
* @return - Video instance object
*/
- (instancetype)initWithSourcePath:(NSString *)sourcePath scene:(NSString *)scene;
@end 

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get video attachment object
NIMVideoObject *object = [[NIMVideoObject alloc] initWithSourcePath:path];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];
  • Data object initialization
@interface NIMVideoObject : NSObject<NIMMessageObject>
/**
 * Initialization method for video instance object
 *
 * @param data - Video data
 * @param extension - Pre-fix of video file
 *
 * @return - Video instance object
 */
- (instancetype)initWithData:(NSData *)data
                extension:(NSString *)extension;
                
/**
* Initialization method for video instance object
*
* @param data - Video data
* @param extension - Pre-fix of video file
* @param scene - Scene type
*
* @return - Video instance object
*/
- (instancetype)initWithData:(NSData *)data
                   extension:(NSString *)extension
                       scene:(NSString *)scene;
@end

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get video attachment object
NIMVideoObject *object = [[NIMVideoObject alloc] initWithData:data extension:@"mp4"];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

Sending a file message

File attachment NIMFileObject parameter list

Parameter Type Description
displayName NSString The file display name is defined by the developer and suitable for upper UI
MD5 NSString MD5 generated based on file data
path NSString Local file path.The SDK does not support file download, but we recommend using this path as the file download address in APP so that the SDK can support cache clearing and other features later
URL NSString Remote file path
fileLength long long File size

The file attachment is initialized in two ways:

  • Path initialization
@interface NIMFileObject : NSObject<NIMMessageObject>
/**
 * Initialization method for file object (by file path)
 *
 * @param sourcePath - File path
 *
 * @return - File instance object
 */
 - (instancetype)initWithSourcePath:(NSString *)sourcePath;
 
 /**
 * Initialization method for file object (by file path)
 *
 * @param sourcePath - File path
 * @param scene - Scene type
 *
 * @return - File instance object
 */
 - (instancetype)initWithSourcePath:(NSString *)sourcePath scene:(NSString *)scene;
@end 

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get file attachment object
NIMFileObject *object = [[NIMFileObject alloc] initWithSourcePath:path];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];
  • Data object initialization
@interface NIMFileObject : NSObject<NIMMessageObject>
/**
 * Initialization method for file instance object
 *
 * @param data - File data
 * @param extension - Pre-fix of file
 *
 * @return - File instance object
 */
- (instancetype)initWithData:(NSData *)data
                    extension:(NSString *)extension;
                    
/**
* Initialization method for file object (by file data)
*
* @param data - File data
* @param extension - Extension name of file
* @param scene - Scene type
* @return - File instance object
*/

- (instancetype)initWithData:(NSData*)data extension:(NSString*)extension scene:(NSString *)scene;
@end

Example:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get video attachment object
NIMFileObject *audioObject = [[NIMFileObject alloc] initWithData:data extension:@"data"];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

Sending a location message

Location attachment NIMLocationObject parameter list

Parameter Type Description
latitude double The latitude location is fed during initialization
longitude double The longitude location is fed during initialization
title NSString Location title is fed during initialization

- Initialization prototype

@interface NIMLocationObject : NSObject<NIMMessageObject>
/**
 * Initialization method for location instance object
 *
 * @param latitude - Latitude
 * @param longitude - Longitude
 * @param title - Description of geographical location
 * @return - Location instance object
 */
- (instancetype)initWithLatitude:(double)latitude
                        longitude:(double)longitude
                            title:(nullable NSString *)title;
@end 

Example of sending a location message to friend Iduser, with altitude (30.27415,120.15515) and location name address:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get location attachment object
NIMLocationObject *object = [[NIMLocationObject alloc] initWithLatitude:120.15515 longitude:30.27415 title:@"address"];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

Tip message sending

Tip messages are mainly for notification in a session. Messaging scenarios: for example, welcome message for entering a session, or tip message of sensitive words in a session. You can also customize a message, but the process is relatively complex.

The tip message attachment does not contain extra information fields, and we recommend putting the tips into the text field of NIMMessage. Extra information can be stored in remoteExt and localExt fields of NIMMessage.

Attachment prototype:

@interface NIMTipObject : NSObject<NIMMessageObject>
@end

Example of sending a tip message welcome to friend Id user:

// Construct detailed session
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get file attachment object
NIMTipObject *object = [[NIMTipObject alloc] init];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;
message.text = @"welcome";
// Error feedback object
NSError *error = nil;
// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

Sending a user-defined message

Serialization and sending

If the developer wants to provide more message types (such as image-text message and red packet message) in addition to several message types predefined by SDK, custom message is inevitable. NIMCustomObject is the prototype of a custom message attachment. The SDK only sends and receives the byte stream serialized and deserialized by id attachment in NIMCustomObject.

At the sending side, the SDK sends the byte stream obtained after encodeAttachment; at the receiving side, the SDK reads the byte stream and parses with the deserialization object set by the developer.

NIMCustomObject attachment prototype:

@interface NIMCustomObject : NSObject<NIMMessageObject>

/**
 * Custom attachment of users
 * @discussion - SDK transfers the result of serializing attachment with The API encodeAttachment.
 */
@property(nullable, nonatomic, strong) id<NIMCustomAttachment> attachment;


/**
 * Register custom message decoder
 *
 * @param decoder - Custom message decoder
 * @disucssion - If users select the custom message type, they shall register the custom message decoder. The decoder deserializes transferred custom messages into the object that can be recognized by the upper app.
 */
+ (void)registerCustomDecoder:(id<NIMCustomAttachmentCoding>)decoder;

@end

Parameter List

Parameter Type Description
attachment id For user-defined attachment encapsulation, you should implement the NIMCustomAttachment, and assign the object to this property at the time of sending a message. The SDK can pass the serialized attachment using the encodeAttachment API

Next, we will introduce the serialization and sending process of custom messages by sending a piece of product information (including product name and link) as an example.

  • Create a product information encapsulation class
// Attachment.h
@interface Attachment : NSObject<NIMCustomAttachment>
// Commodity name
@property (nonatomic,copy) NSString *goodsName;
// Commodity link
@property (nonatomic,copy) NSString *goodsURL;
@end

// Attachment.m
@implementation Attachment

// Realize encodeAttachment API under NIMCustomAttachment
- (NSString *)encodeAttachment
{
    // Encapsulate commodity information into dictionary
    NSDictionary *dict = @{
                            @"goodsName" : self.goodsName,
                            @"goodsURL" : self.goodsURL,
                          };

    // Further serialize acquired content and return
    NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dict options:0 error:nil];
    NSString *content = nil;

    if (jsonData) {
        content = [[NSString alloc] initWithData:jsonData
                                        encoding:NSUTF8StringEncoding];
    }

    return content;
}
@end

NIMCustomAttachment also provides related APIs for uploading and downloading file, as detailed in the API documentation.

  • Send out product information
// Construct detailed session, and send to user for an example
NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];

// Construct custom message attachment
NIMCustomObject *object = [[NIMCustomObject alloc] init];
Attachment *attachment = [[Attachment alloc] init];
object.attachment = attachment;

// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = object;

// Error feedback object
NSError *error = nil;

// Send a message
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

By now, we have introduced the whole serialization and sending process

Deserialization

In cases such as reading a custom message from the local database and receiving a custom message from the recipient, the specific content of the custom message attachments can be fetched after parsing. Taking the product information in the above example as example, we will introduce the deserialization process of custom messages.

  • Create a custom message deserialization class
// CustomAttachmentDecoder.h
@interface CustomAttachmentDecoder : NSObject<NIMCustomAttachmentCoding>
@end


// CustomAttachmentDecoder.m
@implementation CustomAttachmentDecoder
// The decoding method is used for all custom messages. If there are multiple custom messages, you shall extend by the method, and independently implement type determination and version compatibility.
- (id<NIMCustomAttachment>)decodeAttachment:(NSString *)content{
    id<NIMCustomAttachment> attachment;
    NSData *data = [content dataUsingEncoding:NSUTF8StringEncoding];
    if (data) {
        NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
        if ([dict isKindOfClass:[NSDictionary class]]) {
            NSString *goodsName = dict[@"goodsName"];
            NSString *goodsURL = dict[@"goodsURL"]; 
            Attachment *myAttachment = [[Attachment alloc] init];
            myAttachment.goodsName = goodsName;
            myAttachment.goodsURL = goodsURL;
            attachment = myAttachment;
        }
    }
    return attachment;
}
@end
  • Register a custom message parser

Inject the parser in - (BOOL)application: didFinishLaunchingWithOptions::

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
// NIM SDK initialization
[NIMCustomObject registerCustomDecoder:[[CustomAttachmentDecoder alloc] init]];
... 
}
  • Receive custom message

When receiving a message, you should determine whether it is a custom message, further determine the custom message type, and then fetch he corresponding content:

if (message.messageType == NIMMessageTypeCustom) {
    
    NIMCustomObject *object = message.messageObject;
    if ([object.attachment isKindOfClass:[Attachment class]]) {
        Attachment *attachment = (Attachment *)object.attachment;
        
        // The content acquired with attachment.goodsName and attachment.goodsURL is further shown in UI.
        ...
        
        }
        
    }

Message property settings

When sending a message, you can set the message configuration optionsNIMMessage - NIMMessageSetting, mainly determine whether the message is stored in the cloud, or whether it is written to roaming, etc.

/**
 * Configure message
 */
@interface NIMMessageSetting : NSObject
/**
 * It determines that a message is stored in cloud.
 * @discussion - The value is "YES" by default. 
 */
@property (nonatomic,assign)  BOOL    historyEnabled;
/**
 * It determines that a message can be roamed.
 * @discussion - The value is "YES" by default. 
 */
@property (nonatomic,assign)  BOOL    roamingEnabled;
/**
 * It determines that client shall throw the message in the callback for receiving messages when the sender logs in multiple clients synchronously and one message is sent from one client.
 * @discussion - The value is "YES" by default.
 */
@property (nonatomic,assign)  BOOL    syncEnabled;
/**
 * It determines that messages shall be included in unread count.
 * @discussion - The value is "YES" by default. By default, all messages that are received by users will be included in the unread count. If it is set to "NO", related messages will not be included in unread count after being received.
 */
@property (nonatomic,assign)  BOOL    shouldBeCounted;
/**
 * It determines that a message shall be pushed.
 * @discussion - The value is "YES" by default. If value of the field is set to "NO", there is no push notification for a message.
 */
@property (nonatomic,assign)  BOOL    apnsEnabled;
/**
 * It determines that push shall be added with prefix (generally, nickname).
 * @discussion - The value is "YES" by default. If the field is set to "NO", the push notification will not have a prefix (xx:).
 */
@property (nonatomic,assign)  BOOL    apnsWithPrefix;

/**
 * It determines that cc is required.
 * @discussion - The value is "YES" by default, i.e. a message is copied to developers' server (if any).
 */
@property (nonatomic,assign)  BOOL    routeEnabled;

/**
 * It determines that the message is stored offline. If it is set to "false", the message will not be stored in an offline database and cloud message history database.
 * @discussion - The value is "YES" by default
 */
@property (nonatomic,assign)  BOOL    persistEnable;
@end

File resource scenario

The SDK can set the corresponding lifetime of images, audio, videos, and files, etc.

  • Preset NOS resource scenarios

Prototype

@interface NIMSDK : NSObject

/**
* Configure resource scene
* @discussion nos - Rule for pre-defined scene and custom scene
* The settings can be covered. If a pre-defined scene is not set, it is to apply the system default setting.
* sceneDict key-value - There are 3 default pre-defined scenes in the system and the number of custom scenes does not exceed 10.
* key is scene (nsstring type); value is survival time of resource (nsnumber type), accurate to day. 0 is permanent survival.
*/
@property (nonatomic,strong)     NSMutableDictionary *sceneDict;
@end

For example, if set as @{@"nim_icon":@0,@"nim_msg":@0,@"nim_system":@0},

it means that NOS resources such as avatars and other user profiles (nim_icon) permanently exist.

NOS resources of images, audio, videos, and other types of files (nim_msg) permanently exist.

Nim_system is for SDK internal use.

sceneDict-key NIMNOSSceneType enumerated value
nim_icon NIMNOSSceneTypeAvatar
nim_msg NIMNOSSceneTypeMessage
  • File initialization settings

Defined by the initialization methods for various types of attachment messages (image, audio, video, etc.), e.g.

NIMSession *session = [NIMSession session:@"user" type:NIMSessionTypeP2P];
// Get image attachment object, and set corresponding scene to nim_msg
NIMImageObject *imageObject = [[NIMImageObject alloc] initWithImage:image scene:NIMNOSSceneTypeMessage];
// Construct detailed message and include into attachment
NIMMessage *message = [[NIMMessage alloc] init];
message.messageObject = imageObject;
...
[[NIMSDK sharedSDK].chatManager sendMessage:message toSession:session error:&error];

Inserting a local message

If a message shall be inserted to the local database in a service scenario, instead of being sent, then it can be realized using inserting a local message.

The following types of local insertion are currently available:

  • Text message (NIMMessageTypeText)
  • Tip message (NIMMessageTypeTip)
  • Custom message (NIMMessageTypeCustom)
@protocol NIMConversationManager <NSObject>
/**
 * Write a message
 *
 * @param message - Message to be updated
 * @param session - Session to be updated
 * @param completion - Callback that is returned after completion
 * @discussion - When a message is saved successfully, onRecvMessages: under NIMChatManagerDelegate will be received. Callback. Now, it is available to three message types, i.e. NIMMessageTypeText, NIMMessageTypeTip, NIMMessageTypeCustom.
 */
- (void)saveMessage:(NIMMessage *)message
         forSession:(NIMSession *)session
         completion:(nullable NIMUpdateMessageBlock)completion;
@end

Property List

Parameter Type Description
message NIMMessage The above are a type of messages that should be written and have not been sent.
session NIMSession Message session
completion NIMUpdateMessageBlock Callback after completion

The message is written asynchronously, so the developer is not required to open a separate thread in the upper layer, and the message can be called in the current thread.

It is not allowed to insert messages that already exist. After the message has been saved successfully, you will receive onRecvMessages: callback in NIMChatManagerDelegate.

When constructing a NIMMessage message object, you can set accid of the message sender in fromfield and the time of saving message in timestamp field.

Update message

Some message properties can be updated locally, and the local extension field LocalExt and custom message attachment objectNIMCustomObject are currently updatable.

Prototype

@protocol NIMConversationManager <NSObject>
/**
 * Update message history stored in a local database
 *
 * @param message - Message to be updated
 * @param session - Session to be updated
 * @param completion - Callback that is returned after completion
 * @discussion - To ensure completeness of stored message, The API for updating messages provided to upper developers only can be used for updating fields as below: local extension field (LocalExt) and message object of custom message (messageObject)
 */
- (void)updateMessage:(NIMMessage *)message
           forSession:(NIMSession *)session
           completion:(nullable NIMUpdateMessageBlock)completion;
@end

Property List

Parameter Type Description
message NIMMessage For messages that should be updated, the above are available update properties.
session NIMSession Message session
completion NIMUpdateMessageBlock Callback after completion

The message is written asynchronously, so the developer is not required to open a separate thread in the upper layer, and the message can be called in the current thread.

Cancel sending

The developer should enable cancel sending over NIMChatManager protocol in NIMSDK, and can only cancel messages that are being sent (such as sending by large file). Generally, it is used in collaboration with the asynchronous message API. The message is unsuccessfully sent when The API successfully returns a value.

API prototype

@protocol NIMChatManager <NSObject>

/**
 * Cancel the message that is being sent
 *
 * @param message - Target message
 *
 * @return - It determines that invocation is successful.
 */
- (BOOL)cancelSendingMessage:(NIMMessage *)message;

@end
Parameter Type Description
message NIMMessage Message being sent

Resend message

If a message is unsuccessfully sent for network error, you can try to resend the message by calling the message resending API.

Prototype

@protocol NIMChatManager <NSObject>
/**
 * Update message history stored in a local database
 *
 * @param message - Message to be re-sent
 * @param error 
 * 
 * @return - Callback that is returned after sending. The callback here only indicates that the function is invoked and a message shall be sent to complete the callback sendMessage:didCompleteWithError:. As a result, it can determine that the message has been sent to the server.
 */
- - (BOOL)resendMessage:(NIMMessage *)message 
                  error:(NSError *__nullable *)error
@end

Forward messages

All types of messages instead of notification messages can be forwarded to other sessions.

@protocol NIMChatManager <NSObject>
/**
 * Forward a message to other contacts
 *
 * @param message - Message to be forwarded
 * @param session - Session
 * @param error - Callback that is returned after sending. The callback here only indicates that the function is invoked and a message shall be sent to complete the callback sendMessage:didCompleteWithError:. As a result, it can determine that the message has been sent to the server.
 */
- (BOOL)forwardMessage:(NIMMessage *)message
             toSession:(NIMSession *)session
                 error:(NSError **)error
@end
Parameter Type Description
message NIMMessage Message to be forwarded
session NIMSession Session to forward
error NSError Error reason

File transfer management

The SDK supports file transport management and allows the developer to control file transport in the following ways.

  • Actively fetch the transport status of specified messages.
@protocol NIMChatManager <NSObject>
/** 
* It determines that a message is being transmitted (sending / accepting attachment).
*/
- (BOOL)messageInTransport:(NIMMessage *)message;

/** 
* Transmit message progress (sending / accepting attachment)
*/
- (float)messageTransportProgress:(NIMMessage *)message;
@end
  • Monitor file transport:
@protocol NIMChatManagerDelegate <NSObject>
/** 
* A callback for successfully uploading resource file
*/
- (void)uploadAttachmentSuccess:(NSString *)URLString 
                     forMessage:(NIMMessage *)message;

/** 
* Monitor download progress
* @param progress - Download progress, with value range 0 ~ 1
*/
- (void)fetchMessageAttachment:(NIMMessage *)message
                      progress:(float)progress;

/** 
* Monitor download progress
*/
- (void)fetchMessageAttachment:(NIMMessage *)message 
          didCompleteWithError:(nullable NSError *)error
@end

Recall message

Recall message

It allows you to revoke the message that you have sent within a certain time. The default revocation time on the client is 2min, which can be configured on the CommsEase console.

@protocol NIMChatManager <NSObject>
/**
* Revoke a message
*/
- (void)revokeMessage:(NIMMessage *)message
           completion:(NIMRevokeMessageBlock)completion;
           
/**
* Revoke a message, and trigger push. Besides, it is necessary to designate push text and PS apnsPayload, and determine that notification for revocation is included in unread count.
*/
- (void)revokeMessage:(NIMMessage *)message
          apnsContent:(nullable NSString *)apnsContent
          apnsPayload:(nullable NSDictionary *)apnsPayload
      shouldBeCounted:(BOOL)should
           completion:(nullable NIMRevokeMessageBlock)completion;

/**
* Revoke a message
*
* @param message - Message to be revoked
* @param option - Revoked configuration option
* @param completion  A callback for completion
* @discussion - A message is included in unread count.
*/
- (void)revokeMessage:(NIMMessage *)message
               option:(NIMRevokeMessageOption *)option
           completion:(nullable NIMRevokeMessageBlock)completion;
@end
Parameter Type Description
message NIMMessage To-be-recalled message
apnsContent NSDictionary Push content
apnsPayload NSDictionary Push additional information
should BOOL Whether the recall notification is counted into unread message
completion NIMRevokeMessageBlock Callback completion

NIMRevokeMessageOption member:

Parameter Type Description
postscript NSString Recalled postscript
apnsContent NSDictionary Push content
apnsPayload NSDictionary Push additional information
shouldBeCounted BOOL Whether the recall notification is counted into unread message

After the request of revocation message has been called successfully, SDK will invoke the message to upper developer successfully and then automatically delete the message in a local database. If a tip shall be shown after revocation, the developer shall create a tip message independently and call The API of insetting a local message.

The message will not be revoked successfully, if:

  • The message is not delivered to the opposite side
  • The message cannot be revoked due to timeout
  • The message object is not fetched from the local database

In addition, if the revoked message has been pushed to the client with APNs, you can replace the original notification with apnsContent by setting apnsPayload. Refer to notification bar coverage for details.

Monitor message recall

When a message has been successfully recalled by the opposite side, its SDK will trigger a callback.

@protocol NIMChatManagerDelegate <NSObject>
- (void)onRecvRevokeMessageNotification: (NIMRevokeMessageNotification *)notification
@end

NIMRevokeMessageNotification property list:

Property Meaning
notificationType Notification type, such as P2P message recall and team message revocation
fromUserId Recaller
messageFromUserId Recalled message sender
session Recalled message session
timestamp Timestamp of recalled message
message Recalled message
roaming Whether the recall notification is a roaming notification (i.e. whether the message was previously received by other parties)
postscript Recalled postscript

After receiving a message recall notification, the SDK will first find the corresponding message from the local database and then delete it. If you want to receive a tip indicating that this message has been recalled by the opposite side, the developer can construct a tip message and call the method of inserting a local message.

When a message is recalled, the following properties can be configured to recalculate the unread count.

@interface NIMSDKConfig : NSObject
/**
* It determines that revoked messages are included in unread count. The value is "NO" by default. If it is set to "YES", and the revoked message is local and unread, when the message is revoked, unread count of related sessions will subtract 1 to keep consistency in unread count of recent sessions.
*/
@property (nonatomic,assign) BOOL shouldConsiderRevokedMessageUnreadCount;
@end

Read receipt

When the sender wants to know whether the receiver has read the message already sent, the feature of read receipts is enabled.

Single chat message read receipt

The API of sending read receipts is called in the session API and the last message of the current session is fed, which means that all messages have been read.

Send read receipt:

@protocol NIMChatManager <NSObject>
- (void)sendMessageReceipt:(NIMMessageReceipt *)receipt
                completion:(NIMSendMessageReceiptBlock)completion;
@end
Parameter Type Description
receipt NIMMessageReceipt Message receipt
completion NIMSendMessageReceiptBlock Callback completion

Monitor read receipt:

@protocol NIMChatManagerDelegate <NSObject>
- (void)onRecvMessageReceipts:(NSArray<NIMMessageReceipt *> *)receipts
@end

In addition, you can know whether the opposite side has read the message using isRemoteReadin NIMMessage.

Read receipt for messages in team chats

You shall contact the commercial consultant to apply for enabling the acknowledged receipt for team message function. Also, you should limit the number of team members to 100 when enabling this feature.

  • Enable the feature of team message read receipt
@interface NIMSDKConfig : NSObject
/**
 * It determines to enable the team receipt feature.
 * @discussion - The value is "NO" by default. If it is set to "YES", all team receipt-related operations can be valid.
 */
@property (nonatomic,assign) BOOL teamReceiptEnabled
@end
  • Require other team members to send read receipts when they receive this message
@interface NIMMessageSetting : NSObject
/**
 * It determines to send acknowledged receipt when other team members receive the message.
 */
@property (nonatomic, assign) BOOL teamReceiptEnabled
@end
  • The message recipient sends a team message read receipt.
@protocol NIMChatManager <NSObject>
- (void)sendTeamMessageReceipts:(NSArray<NIMMessageReceipt*> *)receipts 
                     completion:(nullable NIMSendTeamMessageReceiptsBlock)completion
@end

Parameter List

Parameter Type Description
receipt NIMMessageReceipt Message receipt
completion NIMSendTeamMessageReceiptsBlock Callback completion
  • The message sender monitors the team message read receipt to fetch the change of the read and unread count
@protocol NIMChatManagerDelegate <NSObject>
- (void)onRecvMessageReceipts:(NSArray<NIMMessageReceipt *> *)receipts;
@end

Parameter List

Parameter Type Description
receipts NSArray<NIMMessageReceipt *> * Message receipt array
  • Actively refresh the team read receipt
@protocol NIMChatManager <NSObject>

/**
 * Refresh read and unread count of team message
 *
 * @param messages - Set of messages to be queried
 * @discussion - If the acknowledged status of a message is changed, it will return to upper developers with the callback onRecvMessageReceipts: under NIMChatManager.
 * The refreshed message must be a team message.
 */
- (void)refreshTeamMessageReceipts:(NSArray<NIMMessage *> *)messages;

@end

Parameter List

Parameter Type Description
message NSArray<NIMMessage *> * To-be-updated message set
  • Query team read receipt details

Include a list of read ids and unread ids. Note that the query details do not change with the number of receipts. If you want to fetch the latest details, you must call this API again.

@protocol NIMChatManager <NSObject>

/**
 * Query acknowledged content of a team message
 *
 * @param NIMMessage - Message to be queried
 * @discussion - The content includes the list of IDs of read and unread accounts.
 * The queried content object will not change with The number of acknowledged accounts. If the latest content shall be acquired, The API shall be invoked again.
 *
 */
- (void)queryMessageReceiptDetail:(NIMMessage *)message
                       completion:(NIMQueryReceiptDetailBlock)completion;
                       
@end                     

Parameter List

Parameter Type Description
message NIMMessage Query message
completion NIMQueryReceiptDetailBlock Query team message receipt details callback
  • Query read receipt details locally

Note: read receipt details fetched locally are not likely to be the latest

@protocol NIMChatManager <NSObject>
/**
* Query the list of read and unread accounts of a single team message in a local database
* Notes!!! : The data acquired here is generally older than the list information before offline status.
*
* @param message - Message to be queried
* @return - List of read and unread accounts of the message
*/
- (nullable NIMTeamMessageReceiptDetail *)localMessageReceiptDetail:(NIMMessage *)message;
@end

Parameter List

Parameter Type Description
message NIMMessage Query message

In addition, you can fetch the team read receipts of the current message using teamReceiptInfo in NIMMessage.

Was this topic helpful?
Yes
No
  • Overview
  • Send messages
  • Send text messages
  • Send image messages
  • Send audio message
  • Sending a video message
  • Sending a file message
  • Sending a location message
  • Tip message sending
  • Sending a user-defined message
  • Serialization and sending
  • Deserialization
  • Message property settings
  • File resource scenario
  • Inserting a local message
  • Update message
  • Cancel sending
  • Resend message
  • Forward messages
  • File transfer management
  • Recall message
  • Recall message
  • Monitor message recall
  • Read receipt
  • Single chat message read receipt
  • Read receipt for messages in team chats