Custom Messages
Custom Regular Messages
We’ll use creating a custom GIF message as an example to demonstrate how to create custom message types.Step 1: Inherit WKMessageContent and Define Message Structure
@interface WKGIFContent : WKMessageContent
// GIF URL
@property(nonatomic, copy) NSString *url;
// Width
@property(nonatomic, assign) NSInteger width;
// Height
@property(nonatomic, assign) NSInteger height;
@end
class WKGIFContent: WKMessageContent {
// GIF URL
var url: String?
// Width
var width: Int = 0
// Height
var height: Int = 0
}
Step 2: Encoding and Decoding
The final message content will be{"type":3,"url":"xxxx","width":xxx,"height":xxx}
@implementation WKGIFContent
// Encode message content to dictionary
- (NSDictionary *)encodeMsg {
NSMutableDictionary *dataDict = [NSMutableDictionary dictionary];
if (self.url) {
dataDict[@"url"] = self.url;
}
dataDict[@"width"] = @(self.width);
dataDict[@"height"] = @(self.height);
return dataDict;
}
// Decode dictionary to message content
- (void)decodeMsg:(NSDictionary *)contentDic {
self.url = contentDic[@"url"];
self.width = [contentDic[@"width"] integerValue];
self.height = [contentDic[@"height"] integerValue];
}
// Message type
- (WKContentType)contentType {
return 3; // Custom type, avoid conflicts with built-in types
}
@end
extension WKGIFContent {
// Encode message content to dictionary
override func encodeMsg() -> [String : Any] {
var dataDict: [String: Any] = [:]
if let url = self.url {
dataDict["url"] = url
}
dataDict["width"] = self.width
dataDict["height"] = self.height
return dataDict
}
// Decode dictionary to message content
override func decodeMsg(_ contentDic: [String : Any]) {
self.url = contentDic["url"] as? String
self.width = contentDic["width"] as? Int ?? 0
self.height = contentDic["height"] as? Int ?? 0
}
// Message type
override func contentType() -> WKContentType {
return 3 // Custom type, avoid conflicts with built-in types
}
}
Step 3: Register Custom Message
// Register in application initialization
[[WKSDK shared] registerMessageContent:[WKGIFContent class]];
// Register in application initialization
WKSDK.shared().registerMessageContent(WKGIFContent.self)
Step 4: Send Custom Message
WKGIFContent *gifContent = [[WKGIFContent alloc] init];
gifContent.url = @"https://example.com/sample.gif";
gifContent.width = 200;
gifContent.height = 150;
WKChannel *channel = [[WKChannel alloc] initWithChannelID:@"user123" channelType:WKChannelTypePerson];
[[WKSDK shared].chatManager sendMessage:gifContent channel:channel];
let gifContent = WKGIFContent()
gifContent.url = "https://example.com/sample.gif"
gifContent.width = 200
gifContent.height = 150
let channel = WKChannel(channelID: "user123", channelType: .person)
WKSDK.shared().chatManager.sendMessage(gifContent, channel: channel)
Custom Attachment Messages
For messages that need to upload files (like images, videos, audio), you need to inherit fromWKMediaMessageContent.
Example: Custom Video Message
@interface WKCustomVideoContent : WKMediaMessageContent
@property(nonatomic, copy) NSString *videoUrl;
@property(nonatomic, assign) NSTimeInterval duration;
@property(nonatomic, copy) NSString *thumbnailUrl;
@end
@implementation WKCustomVideoContent
- (NSDictionary *)encodeMsg {
NSMutableDictionary *dataDict = [NSMutableDictionary dictionary];
if (self.videoUrl) {
dataDict[@"video_url"] = self.videoUrl;
}
if (self.thumbnailUrl) {
dataDict[@"thumbnail_url"] = self.thumbnailUrl;
}
dataDict[@"duration"] = @(self.duration);
return dataDict;
}
- (void)decodeMsg:(NSDictionary *)contentDic {
self.videoUrl = contentDic[@"video_url"];
self.thumbnailUrl = contentDic[@"thumbnail_url"];
self.duration = [contentDic[@"duration"] doubleValue];
}
- (WKContentType)contentType {
return 4; // Custom video type
}
@end
class WKCustomVideoContent: WKMediaMessageContent {
var videoUrl: String?
var duration: TimeInterval = 0
var thumbnailUrl: String?
override func encodeMsg() -> [String : Any] {
var dataDict: [String: Any] = [:]
if let videoUrl = self.videoUrl {
dataDict["video_url"] = videoUrl
}
if let thumbnailUrl = self.thumbnailUrl {
dataDict["thumbnail_url"] = thumbnailUrl
}
dataDict["duration"] = self.duration
return dataDict
}
override func decodeMsg(_ contentDic: [String : Any]) {
self.videoUrl = contentDic["video_url"] as? String
self.thumbnailUrl = contentDic["thumbnail_url"] as? String
self.duration = contentDic["duration"] as? TimeInterval ?? 0
}
override func contentType() -> WKContentType {
return 4 // Custom video type
}
}
Message Extensions
Message Reactions
Add reaction functionality to messages:// Add reaction to message
WKMessage *message = // Get message object
[[WKSDK shared].chatManager addReaction:@"👍" toMessage:message];
// Remove reaction
[[WKSDK shared].chatManager removeReaction:@"👍" fromMessage:message];
// Listen for reaction updates
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(onMessageReactionUpdate:)
name:@"WKMessageReactionUpdateNotification"
object:nil];
- (void)onMessageReactionUpdate:(NSNotification *)notification {
WKMessage *message = notification.userInfo[@"message"];
// Handle reaction update
}
// Add reaction to message
let message: WKMessage = // Get message object
WKSDK.shared().chatManager.addReaction("👍", to: message)
// Remove reaction
WKSDK.shared().chatManager.removeReaction("👍", from: message)
// Listen for reaction updates
NotificationCenter.default.addObserver(
self,
selector: #selector(onMessageReactionUpdate(_:)),
name: NSNotification.Name("WKMessageReactionUpdateNotification"),
object: nil
)
@objc func onMessageReactionUpdate(_ notification: Notification) {
if let message = notification.userInfo?["message"] as? WKMessage {
// Handle reaction update
}
}
Message Replies
Implement message reply functionality:// Reply to a message
WKMessage *originalMessage = // Original message
WKTextContent *replyContent = [[WKTextContent alloc] initWithContent:@"This is a reply"];
// Set reply information
replyContent.reply = [[WKReply alloc] init];
replyContent.reply.messageID = originalMessage.messageID;
replyContent.reply.messageSeq = originalMessage.messageSeq;
replyContent.reply.fromUID = originalMessage.fromUID;
replyContent.reply.payload = originalMessage.content;
WKChannel *channel = [[WKChannel alloc] initWithChannelID:@"group123" channelType:WKChannelTypeGroup];
[[WKSDK shared].chatManager sendMessage:replyContent channel:channel];
// Reply to a message
let originalMessage: WKMessage = // Original message
let replyContent = WKTextContent(content: "This is a reply")
// Set reply information
replyContent.reply = WKReply()
replyContent.reply?.messageID = originalMessage.messageID
replyContent.reply?.messageSeq = originalMessage.messageSeq
replyContent.reply?.fromUID = originalMessage.fromUID
replyContent.reply?.payload = originalMessage.content
let channel = WKChannel(channelID: "group123", channelType: .group)
WKSDK.shared().chatManager.sendMessage(replyContent, channel: channel)
Advanced Configuration
Message Encryption
Enable end-to-end encryption for messages:// Enable encryption
WKOptions *options = [WKSDK shared].options;
options.encryptionEnabled = YES;
options.encryptionKey = @"your-encryption-key";
// Send encrypted message
WKTextContent *content = [[WKTextContent alloc] initWithContent:@"Encrypted message"];
content.encryptionEnabled = YES;
WKChannel *channel = [[WKChannel alloc] initWithChannelID:@"user123" channelType:WKChannelTypePerson];
[[WKSDK shared].chatManager sendMessage:content channel:channel];
// Enable encryption
let options = WKSDK.shared().options
options.encryptionEnabled = true
options.encryptionKey = "your-encryption-key"
// Send encrypted message
let content = WKTextContent(content: "Encrypted message")
content.encryptionEnabled = true
let channel = WKChannel(channelID: "user123", channelType: .person)
WKSDK.shared().chatManager.sendMessage(content, channel: channel)
Message Persistence Control
Control message storage behavior:// Send temporary message (not stored)
WKTextContent *content = [[WKTextContent alloc] initWithContent:@"Temporary message"];
content.header.noPersist = YES;
WKChannel *channel = [[WKChannel alloc] initWithChannelID:@"user123" channelType:WKChannelTypePerson];
[[WKSDK shared].chatManager sendMessage:content channel:channel];
// Send temporary message (not stored)
let content = WKTextContent(content: "Temporary message")
content.header.noPersist = true
let channel = WKChannel(channelID: "user123", channelType: .person)
WKSDK.shared().chatManager.sendMessage(content, channel: channel)
Performance Optimization
Message Caching
Optimize message loading performance:// Configure message cache
WKOptions *options = [WKSDK shared].options;
options.messageCacheCount = 1000; // Cache 1000 messages
options.messageCacheExpiry = 3600; // Cache for 1 hour
// Preload messages
WKChannel *channel = [[WKChannel alloc] initWithChannelID:@"group123" channelType:WKChannelTypeGroup];
[[WKSDK shared].chatManager preloadMessages:channel count:50];
// Configure message cache
let options = WKSDK.shared().options
options.messageCacheCount = 1000 // Cache 1000 messages
options.messageCacheExpiry = 3600 // Cache for 1 hour
// Preload messages
let channel = WKChannel(channelID: "group123", channelType: .group)
WKSDK.shared().chatManager.preloadMessages(channel, count: 50)
Batch Operations
Perform batch operations for better performance:// Batch send messages
NSArray<WKMessageContent *> *messages = @[
[[WKTextContent alloc] initWithContent:@"Message 1"],
[[WKTextContent alloc] initWithContent:@"Message 2"],
[[WKTextContent alloc] initWithContent:@"Message 3"]
];
WKChannel *channel = [[WKChannel alloc] initWithChannelID:@"group123" channelType:WKChannelTypeGroup];
[[WKSDK shared].chatManager batchSendMessages:messages channel:channel];
// Batch send messages
let messages: [WKMessageContent] = [
WKTextContent(content: "Message 1"),
WKTextContent(content: "Message 2"),
WKTextContent(content: "Message 3")
]
let channel = WKChannel(channelID: "group123", channelType: .group)
WKSDK.shared().chatManager.batchSendMessages(messages, channel: channel)
Error Handling
Advanced Error Handling
Implement comprehensive error handling:// Set error handler
[[WKSDK shared].chatManager setErrorHandler:^(WKError *error, WKMessage *message) {
switch (error.code) {
case WKErrorCodeNetworkUnavailable:
// Handle network error
[self handleNetworkError:error message:message];
break;
case WKErrorCodeMessageTooLarge:
// Handle message size error
[self handleMessageSizeError:error message:message];
break;
case WKErrorCodePermissionDenied:
// Handle permission error
[self handlePermissionError:error message:message];
break;
default:
// Handle other errors
[self handleGenericError:error message:message];
break;
}
}];
// Set error handler
WKSDK.shared().chatManager.setErrorHandler { error, message in
switch error.code {
case .networkUnavailable:
// Handle network error
self.handleNetworkError(error, message: message)
case .messageTooLarge:
// Handle message size error
self.handleMessageSizeError(error, message: message)
case .permissionDenied:
// Handle permission error
self.handlePermissionError(error, message: message)
default:
// Handle other errors
self.handleGenericError(error, message: message)
}
}
Best Practices
- Custom Message Types: Use unique type IDs to avoid conflicts
- Memory Management: Properly manage memory for large attachments
- Error Handling: Implement comprehensive error handling for all operations
- Performance: Use batch operations for multiple messages
- Security: Enable encryption for sensitive communications
- Caching: Configure appropriate cache settings for your use case

