融云 iOS SDK 自定义消息类型及展示

通过以下代码,开发者可实现自定义消息的类型及 UI 展示:

1、新建自定义消息类 “SimpleMessage.h” 文件,代码如下:

#import <RongIMLib/RongIMLib.h>
#import <RongIMLib/RCMessageContentView.h>

#define RCLocalMessageTypeIdentifier @”RC:SimpleMsg”
/**
* 文本消息类定义
*/
@interface SimpleMessage : RCMessageContent <NSCoding,RCMessageContentView>
/** 文本消息内容 */
@property(nonatomic, strong) NSString* content;

/**
* 附加信息
*/
@property(nonatomic, strong) NSString* extra;

/**
* 根据参数创建文本消息对象
* @param content 文本消息内容
*/
+(instancetype)messageWithContent:(NSString *)content;

@end

 

`SimpleMessage.m` 文件代码如下:

#import “SimpleMessage.h”
#import <RongIMLib/RCUtilities.h>

@implementation SimpleMessage

+(instancetype)messageWithContent:(NSString *)content {
SimpleMessage *msg = [[SimpleMessage alloc] init];
if (msg) {
msg.content = content;
}

return msg;
}

+(RCMessagePersistent)persistentFlag {
return (MessagePersistent_ISPERSISTED | MessagePersistent_ISCOUNTED);
}

#pragma mark – NSCoding protocol methods
#define KEY_TXTMSG_CONTENT @”content”
#define KEY_TXTMSG_EXTRA @”extra”

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
self.content = [aDecoder decodeObjectForKey:KEY_TXTMSG_CONTENT];
self.extra = [aDecoder decodeObjectForKey:KEY_TXTMSG_EXTRA]; }
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.content forKey:KEY_TXTMSG_CONTENT];
[aCoder encodeObject:self.extra forKey:KEY_TXTMSG_EXTRA];

}

#pragma mark – RCMessageCoding delegate methods

-(NSData *)encode {

NSMutableDictionary *dataDict=[NSMutableDictionary dictionary];
[dataDict setObject:self.content forKey:@"content"];
if (self.extra) {
[dataDict setObject:self.extra forKey:@"extra"];
}

if (self.senderUserInfo) {
NSMutableDictionary *__dic=[[NSMutableDictionary alloc]init];
if (self.senderUserInfo.name) {
[__dic setObject:self.senderUserInfo.name forKeyedSubscript:@"name"];
}
if (self.senderUserInfo.portraitUri) {
[__dic setObject:self.senderUserInfo.portraitUri forKeyedSubscript:@"icon"];
}
if (self.senderUserInfo.userId) {
[__dic setObject:self.senderUserInfo.userId forKeyedSubscript:@"id"];
}
[dataDict setObject:__dic forKey:@"user"];
}

//NSDictionary* dataDict = [NSDictionary dictionaryWithObjectsAndKeys:self.content, @"content", nil];
NSData *data = [NSJSONSerialization dataWithJSONObject:dataDict
options:kNilOptions
error:nil];
return data;
}

-(void)decodeWithData:(NSData *)data {
__autoreleasing NSError* __error = nil;
if (!data) {
return;
}
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data
options:kNilOptions
error:&__error];

}

- (NSString *)conversationDigest
{
return @”会话列表要显示的内容”;
}
+(NSString *)getObjectName {
return @”xxxx”;
}
#if ! __has_feature(objc_arc)
-(void)dealloc
{
[super dealloc];
}
#endif//__has_feature(objc_arc)
@end

2、新建自定义消息展示 UI “SimpleMessageCell.h” 文件代码如下:

/**
* 文本消息Cell
*/
@interface SimpleMessageCell : RCMessageCell

/**
* 消息显示Label
*/
@property(strong, nonatomic) RCAttributedLabel *textLabel;

/**
* 消息背景
*/
@property(nonatomic, strong) UIImageView *bubbleBackgroundView;

/**
* 设置消息数据模型
*
* @param model 消息数据模型
*/
- (void)setDataModel:(RCMessageModel *)model;
@end

“SimpleMessageCell.m” 文件代码如下:

@interface SimpleMessageCell ()

- (void)initialize;

@end

@implementation SimpleMessageCell

- (NSDictionary *)attributeDictionary {
if (self.messageDirection == MessageDirection_SEND) {
return @{
@(NSTextCheckingTypeLink) : @{NSForegroundColorAttributeName : [UIColor blueColor]},
@(NSTextCheckingTypePhoneNumber) : @{NSForegroundColorAttributeName : [UIColor blueColor]}
};
} else {
return @{
@(NSTextCheckingTypeLink) : @{NSForegroundColorAttributeName : [UIColor blueColor]},
@(NSTextCheckingTypePhoneNumber) : @{NSForegroundColorAttributeName : [UIColor blueColor]}
};
}
return nil;
}

- (NSDictionary *)highlightedAttributeDictionary {
return [self attributeDictionary];
}
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self initialize];
}
return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
[self initialize];
}
return self;
}
- (void)initialize {
self.bubbleBackgroundView = [[UIImageView alloc] initWithFrame:CGRectZero];
[self.messageContentView addSubview:self.bubbleBackgroundView];

self.textLabel = [[RCAttributedLabel alloc] initWithFrame:CGRectZero];
self.textLabel.attributeDictionary = [self attributeDictionary];
self.textLabel.highlightedAttributeDictionary = [self highlightedAttributeDictionary];
[self.textLabel setFont:[UIFont systemFontOfSize:Text_Message_Font_Size]];

self.textLabel.numberOfLines = 0;
[self.textLabel setLineBreakMode:NSLineBreakByWordWrapping];
[self.textLabel setTextAlignment:NSTextAlignmentLeft];
[self.textLabel setTextColor:[UIColor blackColor]];
//[self.textLabel setBackgroundColor:[UIColor yellowColor]];

[self.bubbleBackgroundView addSubview:self.textLabel];
self.bubbleBackgroundView.userInteractionEnabled = YES;
UILongPressGestureRecognizer *longPress =
[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressed:)];
[self.bubbleBackgroundView addGestureRecognizer:longPress];
}

- (void)setDataModel:(RCMessageModel *)model {
[super setDataModel:model];

[self setAutoLayout];
}
- (void)setAutoLayout {
RCTextMessage *_textMessage = (RCTextMessage *)self.model.content;
if (_textMessage) {
self.textLabel.text = _textMessage.content;
} else {
//DebugLog(@”[RongIMKit]: RCMessageModel.content is NOT RCTextMessage object”);
}
// ios 7
CGSize __textSize =
[_textMessage.content
boundingRectWithSize:CGSizeMake(self.baseContentView.bounds.size.width -
(10 + [RCIM sharedKit].globalMessagePortraitSize.width + 10) * 2 – 5 -
35,
MAXFLOAT)
options:NSStringDrawingTruncatesLastVisibleLine | NSStringDrawingUsesLineFragmentOrigin |
NSStringDrawingUsesFontLeading
attributes:@{
NSFontAttributeName : [UIFont systemFontOfSize:Text_Message_Font_Size]
} context:nil]
.size;
__textSize = CGSizeMake(ceilf(__textSize.width), ceilf(__textSize.height));
CGSize __labelSize = CGSizeMake(__textSize.width + 5, __textSize.height + 5);

CGFloat __bubbleWidth = __labelSize.width + 15 + 20 < 50 ? 50 : (__labelSize.width + 15 + 20);
CGFloat __bubbleHeight = __labelSize.height + 5 + 5 < 35 ? 35 : (__labelSize.height + 5 + 5);

CGSize __bubbleSize = CGSizeMake(__bubbleWidth, __bubbleHeight);

CGRect messageContentViewRect = self.messageContentView.frame;

if (MessageDirection_RECEIVE == self.messageDirection) {
messageContentViewRect.size.width = __bubbleSize.width;
self.messageContentView.frame = messageContentViewRect;

self.bubbleBackgroundView.frame = CGRectMake(0, 0, __bubbleSize.width, __bubbleSize.height);

self.textLabel.frame = CGRectMake(20, 5, __labelSize.width, __labelSize.height);
self.bubbleBackgroundView.image = [self imageNamed:@"chat_from_bg_normal" ofBundle:@"RongCloud.bundle"];
UIImage *image = self.bubbleBackgroundView.image;
self.bubbleBackgroundView.image = [self.bubbleBackgroundView.image
resizableImageWithCapInsets:UIEdgeInsetsMake(image.size.height * 0.8, image.size.width * 0.8,
image.size.height * 0.2, image.size.width * 0.2)];
} else {
messageContentViewRect.size.width = __bubbleSize.width;
messageContentViewRect.origin.x =
self.baseContentView.bounds.size.width -
(messageContentViewRect.size.width + 10 + [RCIM sharedKit].globalMessagePortraitSize.width + 10);
self.messageContentView.frame = messageContentViewRect;

self.bubbleBackgroundView.frame = CGRectMake(0, 0, __bubbleSize.width, __bubbleSize.height);

self.textLabel.frame = CGRectMake(15, 5, __labelSize.width, __labelSize.height);

self.bubbleBackgroundView.image = [self imageNamed:@"chat_to_bg_normal" ofBundle:@"RongCloud.bundle"];
UIImage *image = self.bubbleBackgroundView.image;
self.bubbleBackgroundView.image = [self.bubbleBackgroundView.image
resizableImageWithCapInsets:UIEdgeInsetsMake(image.size.height * 0.8, image.size.width * 0.2,
image.size.height * 0.2, image.size.width * 0.8)];
}

}
- (UIImage *)imageNamed:(NSString *)name ofBundle:(NSString *)bundleName {
UIImage *image = nil;
NSString *image_name = [NSString stringWithFormat:@"%@.png", name];
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString *bundlePath = [resourcePath stringByAppendingPathComponent:bundleName];
NSString *image_path = [bundlePath stringByAppendingPathComponent:image_name];
image = [[UIImage alloc] initWithContentsOfFile:image_path];

return image;
}

- (void)longPressed:(id)sender {
UILongPressGestureRecognizer *press = (UILongPressGestureRecognizer *)sender;
if (press.state == UIGestureRecognizerStateEnded) {
//DebugLog(@”long press end”);
return;
} else if (press.state == UIGestureRecognizerStateBegan) {
[self.delegate didLongTouchMessageCell:self.model inView:self.bubbleBackgroundView];
}
}

@end

3、注册自定义消息类及 UI

SDK 初始化方法 initWithAppKey 之后后注册消息类型
[[RCIMClient sharedClient]registerMessageType:SimpleMessage.class];

会话页面注册 UI
[self registerClass:SimpleMessageCell.class forCellWithReuseIdentifier:@"SimpleMessageCell"];

4、重写会话页面自定义消息展示的两个方法

-(RCMessageBaseCell *)rcConversationCollectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
RCMessageModel *model = self.conversationDataRepository[indexPath.row];
NSString * cellIndentifier=@”SimpleMessageCell”;
RCMessageBaseCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIndentifier           forIndexPath:indexPath];
[cell setDataModel:model];
return cell;
}
-(CGSize)rcConversationCollectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
//返回自定义cell的实际高度
return CGSizeMake(300, 60);
}

至此已完成自定义消息类型及展示,谢谢!