Sending Messages
Update time: 2024/08/20 15:45:46
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.
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
objc@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.
objc@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.
objc@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:
objc@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
:
objc// 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
objc@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:
objc// 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
objc@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:
objc// 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
objc@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:
objc// 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:
objc@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
objc@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:
objc// 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
objc@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:
objc// 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
objc@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:
objc// 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
objc@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:
objc// 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
objc@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:
objc// 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
objc@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:
objc// 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
objc@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
:
objc// 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:
objc@interface NIMTipObject : NSObject<NIMMessageObject>
@end
Example of sending a tip message welcome
to friend Id user
:
objc// 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
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:
objc@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
objc// 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
objc// 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
objc// 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:
:
objc- (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:
objcif (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.
objc/**
* 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
objc@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.
objcNIMSession *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)
objc@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 from
field 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
objc@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
objc@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
objc@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.
objc@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.
objc@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:
objc@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.
objc@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.
objc@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.
objc@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:
objc@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:
objc@protocol NIMChatManagerDelegate <NSObject>
- (void)onRecvMessageReceipts:(NSArray<NIMMessageReceipt *> *)receipts
@end
In addition, you can know whether the opposite side has read the message using isRemoteRead
in 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
objc@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
objc@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.
objc@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
objc@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
objc@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.
objc@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
objc@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
.