Message Extensions
The message extension feature allows adding Key/Value-based status identifiers to message objects (RCMessage). Message extension information can be set or updated before or after sending, enabling business requirements such as message comments, gift claiming, and order status changes.
- Message extensions are only supported in one-to-one chats, group chats, ultra groups. Not supported for chatrooms and system conversations.
- Whether a message can carry or have extension information set is determined by the
canIncludeExpansionproperty ofRCMessagewhen sending. This property must be set before sending and cannot be modified afterward. - A single message can have up to 20 extension KV pairs set at once, with a total limit of 300 KV pairs. In concurrent scenarios, any excess beyond 300 will be discarded.
- If cloud storage for historical messages is enabled, historical messages retrieved from the server will also carry any set extension information.
- 4.x SDKs support message extensions starting from version 4.0.3.
- Each message extension update generates a built-in notification message, so frequent updates may produce a large number of messages.
Implementation Approach
Taking order status changes as an example, message display states can be modified through message extensions. For order confirmation:
- When a user places an order for a product, the merchant needs to send an order confirmation message. When sending the message, set the
canIncludeExpansionproperty to allow extensions, along with Key/Value pairs identifying the order status. For example, before user confirmation, a Key/Value pair can indicate the order status as unconfirmed. - After the user clicks to confirm (or performs other confirmation actions), the order message status needs to change to confirmed. At this point, use the
updateMessageExpansionmethod to update the message's extension information, marking it as confirmed, while also modifying the local display style. - The merchant monitors message extension status changes to track user-specified message state updates, displaying the latest order status based on the most recent extension information.
Message comments and gift claiming can follow similar approaches:
- Gift claiming: Change message display states through extensions. For example, when sending a gift to a user, the default state is unclaimed. After the user clicks, set the message extension to claimed.
- Message comments: Add comment information by setting extension data on the original message.
Monitoring Message Extension Data Changes
After the initiating party updates or deletes extension data using IMLib SDK methods, the receiving party can monitor these changes through the RCMessageExpansionDelegate protocol methods and handle them accordingly.
To implement this, developers need to conform to the RCMessageExpansionDelegate protocol. It's recommended to set the delegate after initializing the IMLib SDK but before connecting to IM.
[RCIMClient sharedRCIMClient].messageExpansionDelegate = self;
Delegate Methods
@protocol RCMessageExpansionDelegate <NSObject>
/**
Callback for message extension information updates
@param expansionDic The updated Key/Value pairs in the message extension
@param message The message
@discussion expansionDic only contains the updated Key/Value pairs, not all data. To get all Key/Value pairs, use the message's expansionDic property.
*/
- (void)messageExpansionDidUpdate:(NSDictionary<NSString *, NSString *> *)expansionDic
message:(RCMessage *)message;
/**
Callback for message extension information deletion
@param keyArray The list of keys for deleted Key/Value pairs in the message extension
@param message The message
*/
- (void)messageExpansionDidRemove:(NSArray<NSString *> *)keyArray
message:(RCMessage *)message;
@end
Enabling Message Extensibility (Before Sending Only)
After creating a new message, set the canIncludeExpansion property of RCMessage to enable or disable extensibility for that message.
- The
canIncludeExpansionproperty must be set before sending the message.
Method Prototype
/// Whether the message can include extension information
///
/// This property is determined when the message is sent and cannot be modified afterward
/// Extensions are only supported in one-to-one chats, group chats, and ultra groups; other conversation types cannot set extensions
@property (nonatomic, assign) BOOL canIncludeExpansion;
Parameter Description
| Parameter | Type | Description |
|---|---|---|
| canIncludeExpansion | BOOL | Whether the message can be extended. YES: The message allows extension information. NO: The message does not allow extension information. This setting cannot be changed after sending. |
Example Code
RCTextMessage *txt = [RCTextMessage messageWithContent:text];
RCMessage *msg = [[RCMessage alloc] initWithType:self.conversationType targetId:self.targetId direction:(MessageDirection_SEND) messageId:-1 content:txt];
msg.canIncludeExpansion = YES;
If you need to insert a message locally before sending (e.g., for content review), you must set this property when inserting the message (see [Insert Message]). Once inserted locally, the returned message does not support modifying the canIncludeExpansion property to change extensibility.
Setting Message Extension Data (Before Sending Only)
If a message has extensibility enabled, you can set extension data through the expansionDic property of RCMessage. This can only be called before sending the message.
Method Prototype
/*!
Message extension information dictionary
@discussion Extensions are supported in one-to-one chats, groups, and ultra groups; other conversation types cannot set extensions
@discussion By default, extension keys cannot exceed 32 characters, values cannot exceed 4096 characters, a maximum of 20 pairs can be set at once, and a message cannot have more than 300 extensions total
*/
@property (nonatomic, strong) NSDictionary<NSString *, NSString *> *expansionDic;
Parameter Description
| Parameter | Type | Description |
|---|---|---|
| expansionDic | NSDictionary | Message extension information. Maximum 20 KV pairs can be set at once. A single message can have up to 300 extensions total.
|
The following example sets extension data for the previously created message msg and sends this text message via sendMessage.
Example Code
msg.expansionDic = @{@"key1":@"value1",@"key2":@"value2"};
[[RCCoreClient sharedCoreClient] sendMessage:msg pushContent:nil pushData:nil successBlock:^(RCMessage *successMessage) {
} errorBlock:^(RCErrorCode nErrorCode, RCMessage *errorMessage) {
}];
The message sent in the above example will carry the extension data from the expansionDic property. After successful sending, the IMLib SDK stores the message and its extension data in the local database.
If sending a message that already exists in the local database (see [Insert Message]), note that:
-
(SDK ≧ 5.3.4) After successful sending, the IMLib SDK refreshes the message's extension data in the local database.
-
(SDK < 5.3.4) After successful sending, the IMLib SDK cannot refresh the message's extension data in the local database. It's recommended to send the message first, then update both local and remote extension information by calling
updateMessageExpansion. The receiving end can monitor and receive extension data updates. -
Each time message extensions are updated (or deleted), the IMLib SDK internally sends a signaling message of type
RC:MsgExMsgto conversation counterparts. Therefore, frequent updates will generate a large number of messages. -
Each client can set extension information as long as the limit isn't reached. In concurrent scenarios, settings exceeding 300 will be discarded.
-
If your business scenario requires server-side processing, you can also set one-to-one/group chat extensions via the application server. :::
Method Signature
- (void)updateMessageExpansion:(NSDictionary<NSString *, NSString *> *)expansionDic
messageUId:(NSString *)messageUId
success:(nullable void (^)(void))successBlock
error:(nullable void (^)(RCErrorCode status))errorBlock;
#### Parameters
| Parameter | Type | Description |
|:-------------|:-------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| expansionDic | NSDictionary | Key-value pairs for message extension updates.<ul><li>Keys support alphanumeric characters and special symbols `+ = - _`, with a maximum length of 32 characters (Chinese not supported).</li><li>(SDK < 5.2.0) Value max: 64 chars</li><li>(SDK ≥ 5.2.0) Value max: 4096 chars</li></ul> |
| messageUId | NSString | Message UID |
| successBlock | Block | Success callback |
| errorBlock | Block | Failure callback containing error code [RCErrorCode]
#### Sample Code |
```objectivec
// Update message extensions
[[RCCoreClient sharedCoreClient] updateMessageExpansion:dic messageUId:message.messageUId success:^{
// Handle UI refresh after extension update here
} error:^(RCErrorCode status) {
}];
## Delete Extension Data
After sending a message, you can call `removeMessageExpansionForKey` to delete specific key-value pairs from message extensions (only for messages with extensible properties enabled). After deletion, handle UI refresh in the success callback, while conversation counterparts receive notifications through the message extension listener.
#### Method Signature
```objectivec
- (void)removeMessageExpansionForKey:(NSArray<NSString *> *)keyArray
messageUId:(NSString *)messageUId
success:(nullable void (^)(void))successBlock
error:(nullable void (^)(RCErrorCode status))errorBlock;
#### Parameters
| Parameter | Type | Description |
|:------------:|:--------:|:------------------------------------------------:|
| keyArray | NSArray | List of keys to delete from message extensions |
| messageUId | NSString | Message UID |
| successBlock | Block | Success callback |
| errorBlock | Block | Failure callback containing error code [RCErrorCode] |
#### Sample Code
```objectivec
[[RCIMClient sharedRCIMClient] removeMessageExpansionForKey:keyArray messageUId:messageUId success:^{
} error:^(RCErrorCode status) {
}];
<!-- links -->
[Insert Message]: ./insert.md
<!-- api links -->
[RCErrorCode]: https://doc.rongcloud.cn/apidoc/imlibcore-ios/latest/zh_CN/documentation/rongimlibcore/rcerrorcode?language=objc