300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > 集成网易云信实现自定义消息(类似淘宝聊天发送商品信息)

集成网易云信实现自定义消息(类似淘宝聊天发送商品信息)

时间:2018-12-28 17:37:14

相关推荐

集成网易云信实现自定义消息(类似淘宝聊天发送商品信息)

上篇文章,我们整理了网易云信的快速集成过程.有兴趣的小伙伴可以移步到:ios集成网易云信IM功能遇到的坑.简单的实现一对一聊天界面或者查看最近联系人列表.我们只需直接调用NIMKit里面的NIMSessionViewController 和 NIMSessionListViewController这两个类方法.就能实现功能.但是简单的聊天可能满足不了我们项目需要.比如要实现电商平台中,我们浏览商品.突然觉得商品还不错.去找客服聊天.那么这时候我们希望把浏览的商品也给推送过去.好让客服知道我们在看什么.并且,自定义消息设置成可点击的,方便可以点击查看商品详情.

今天我就给大家整理下怎么实现自定义消息发送.

其实具体也可以参考官方demo中实现发送大表情效果过程.毕竟大表情图片其实也是一种自定义消息发送的表现形式.

那么,发送自定义消息,我大概整理了下,觉得可以分为四部分,这样实现起来逻辑会觉得比较清晰.如下:

1.实现自定义消息model类.承接数据部分.

2.实现自定义消息view 类,承接自定义UI部分.

3.实现自定义布局配置类.

4.消息解析器(解析消息,辨别消息类型!)

最后一步,就是在入口类中注册拉起解析器和自定义布局.这样,系统才能识别消息类型,并实现自定义布局.

那!第一步,我们实现自定义消息model类,承接数据部分.

创建一个类,继承与NSObject.并实现NIMKit <NIMCustomAttachment,NTESCustomAttachmentInfo>两个协议方法.

.h类中:

#import <Foundation/Foundation.h>

#import "NIMKit.h"

#import "NTESCustomAttachmentDefines.h"

@interface NTESSendShopGoodsAttachment :NSObject<NIMCustomAttachment,NTESCustomAttachmentInfo>

//添加自定义消息元素

@property(nonatomic,copy)NSString*headerImage;

@property(nonatomic,copy)NSString*nameLabel;

@property(nonatomic,copy)NSString*priceLabel;

//数据源承接类

@property(nonatomic,strong)NSDictionary*messageDic;

@end

.m类中:

#import "NTESSendShopGoodsAttachment.h"

@implementation NTESSendShopGoodsAttachment

//对数据源进行类型分配.

- (NSString *)encodeAttachment

{

NSDictionary *dictContent =@{CM_GOODS_IMG:self.headerImage,CM_GOODS_NAME:self.nameLabel,CM_GOODS_PRICE:self.priceLabel};

NSDictionary *dict =@{CMType :@(CustomMessageSendShopGoods),

CMData :dictContent};

NSData *data = [NSJSONSerializationdataWithJSONObject:dict

options:0

error:nil];

NSString *content =nil;

if (data) {

content = [[NSStringalloc] initWithData:data

encoding:NSUTF8StringEncoding];

}

return content;

}

//实例化元素(懒加载...)

-(NSString *)headerImage{

if (!_headerImage) {

_headerImage =nil;

}

return_headerImage;

}

-(NSString *)nameLabel{

if (!_nameLabel) {

_nameLabel =nil;

}

return_nameLabel;

}

-(NSString *)priceLabel

{

if (!_priceLabel) {

_priceLabel =nil;

}

return_priceLabel;

}

//数据源setter方法实现

-(void)setMessageDic:(NSDictionary *)messageDic

{

_messageDic =messageDic;

//给元素赋值

self.headerImage =[_messageDic[@"picture"]substringFromIndex:3];

self.nameLabel =_messageDic[@"name"];

self.priceLabel =_messageDic[@"price"];

}

//设置自定义消息Bounds

- (CGSize)contentSize:(NIMMessage *)message cellWidth:(CGFloat)width{

returnCGSizeMake(200,70);

}

- (UIEdgeInsets)contentViewInsets:(NIMMessage *)message

{

if (message.session.sessionType == NIMSessionTypeChatroom)

{

CGFloat bubbleMarginTopForImage =15.f;

CGFloat bubbleMarginLeftForImage =12.f;

returnUIEdgeInsetsMake(bubbleMarginTopForImage,bubbleMarginLeftForImage,0,0);

}

else

{

CGFloat bubbleMarginForImage =3.f;

CGFloat bubbleArrowWidthForImage =5.f;

if (message.isOutgoingMsg) {

returnUIEdgeInsetsMake(bubbleMarginForImage,bubbleMarginForImage,bubbleMarginForImage,bubbleMarginForImage + bubbleArrowWidthForImage);

}else{

returnUIEdgeInsetsMake(bubbleMarginForImage,bubbleMarginForImage + bubbleArrowWidthForImage, bubbleMarginForImage,bubbleMarginForImage);

}

}

}

//指向自定义view类

- (NSString *)cellContent:(NIMMessage *)message{

return@"NTESSessionSendShopGoodsContentView";

}

那!我们现在创建自定义view类.自定义view类继承与父类: NIMSessionMessageContentView .h文件:

#import "NIMSessionMessageContentView.h"

//用于点击事件触发标识符!!!

extern NSString *const SendCustomWithGoodsClick;

@interface NTESSessionSendShopGoodsContentView :NIMSessionMessageContentView

//自定义展示商品信息控件

@property(nonatomic,strong)UIImageView *headerImg;

@property(nonatomic,strong)UILabel*nameLa;

@property(nonatomic,strong)UILabel*priceLa;

@end

.m文件:

#import "NTESSessionSendShopGoodsContentView.h"

#import "NTESSendShopGoodsAttachment.h"

#import "UIView+SL.h"

#import "UIImage+Image.h"

NSString *const SendCustomWithGoodsClick =@"SendCustomWithGoodsClick";

@interface NTESSessionSendShopGoodsContentView()

//添加手势

@property (nonatomic,strong)UITapGestureRecognizer*top;

@end

@implementation NTESSessionSendShopGoodsContentView

- (instancetype)initSessionMessageContentView{

self = [superinitSessionMessageContentView];

if (self) {

self.opaque =YES;

//点击自定义消息cell,添加手势

self.top = [[UITapGestureRecognizeralloc] initWithTarget:selfaction:@selector(tapGesture:)];

[selfaddGestureRecognizer:self.top];

self.headerImg =[[UIImageViewalloc]initWithFrame:CGRectZero];

[selfaddSubview:self.headerImg];

self.nameLa =[[UILabel alloc]initWithFrame:CGRectZero];

_nameLa.font =[UIFontsystemFontOfSize:13];

_nameLa.numberOfLines =0;

[selfaddSubview:self.nameLa];

self.priceLa =[[UILabelalloc]initWithFrame:CGRectZero];

_priceLa.font =[UIFontsystemFontOfSize:12];

_priceLa.textColor =[UIColororangeColor];

[selfaddSubview:self.priceLa];

}

returnself;

}

#pragma mark - 点击手势

- (void)tapGesture:(UITapGestureRecognizer *)recognizer {

if ([self.delegaterespondsToSelector:@selector(onCatchEvent:)]) {

NIMKitEvent *event = [[NIMKitEventalloc] init];

//添加自定义消息标识符

event.eventName =SendCustomWithGoodsClick;

event.messageModel =self.model;

event.data =self;

[self.delegateonCatchEvent:event];

}

}

//赋值

- (void)refresh:(NIMMessageModel *)data{

[superrefresh:data];

NIMCustomObject *customObject = (NIMCustomObject*)data.message.messageObject;

id attachment = customObject.attachment;

if ([attachmentisKindOfClass:[NTESSendShopGoodsAttachmentclass]]) {

self.nameLa.text =[attachmentnameLabel ];

IMAGE_URL(self.headerImg,[attachment headerImage],@"header.jpg");

self.priceLa.text =[attachmentpriceLabel];

}

}

//自定义view元素控件坐标设置

- (UIImage *)chatBubbleImageForState:(UIControlState)state outgoing:(BOOL)outgoing{

self.headerImg.frame =CGRectMake(7,8,54,54);

self.nameLa.frame =CGRectMake(70,5,125,40);

self.priceLa.frame =CGRectMake(70,50,70,15);

//背景颜色

return [UIImageimageWithColor:[UIColorwhiteColor]];

}

@end

自定义cell布局类继承父类: NIMCellLayoutConfig .h文件:

#import "NIMCellLayoutConfig.h"

#import "NIMKit.h"

@interface NTESCellLayoutConfig :NIMCellLayoutConfig<NIMCellLayoutConfig>

@end

#import "NTESCellLayoutConfig.h"

#import "NTESSessionCustomContentConfig.h"

@interface NTESCellLayoutConfig ()

@property (nonatomic,strong) NSArray *types;

@property (nonatomic,strong) NTESSessionCustomContentConfig *sessionCustomconfig;

@end

.m文件:

@implementation NTESCellLayoutConfig

- (instancetype)init

{

if (self = [superinit])

{

//添加消息类型!我们写在了第一个

_types =@[

@"NTESSendShopGoodsAttachment",

@"NTESSnapchatAttachment",

@"NTESChartletAttachment",

@"NTESWhiteboardAttachment"

];

_sessionCustomconfig = [[NTESSessionCustomContentConfigalloc] init];

}

returnself;

}

#pragma mark - NIMCellLayoutConfig

- (CGSize)contentSize:(NIMMessageModel *)model cellWidth:(CGFloat)width{

NIMMessage *message = model.message;

//检查是不是当前支持的自定义消息类型

if ([selfisSupportedCustomMessage:message]) {

return [_sessionCustomconfigcontentSize:width message:message];

}

//检查是不是聊天室文本消息

if ([selfisChatroomTextMessage:message]) {

// return [_chatroomTextConfig contentSize:width message:message];

}

//如果没有特殊需求,就走默认处理流程

return [supercontentSize:model

cellWidth:width];

}

- (NSString *)cellContent:(NIMMessageModel *)model{

NIMMessage *message = model.message;

//检查是不是当前支持的自定义消息类型

if ([selfisSupportedCustomMessage:message]) {

return [_sessionCustomconfigcellContent:message];

}

//检查是不是聊天室文本消息

if ([selfisChatroomTextMessage:message]) {

// return [_chatroomTextConfig cellContent:message];

}

//如果没有特殊需求,就走默认处理流程

return [supercellContent:model];

}

- (UIEdgeInsets)contentViewInsets:(NIMMessageModel *)model

{

NIMMessage *message = model.message;

//检查是不是当前支持的自定义消息类型

if ([selfisSupportedCustomMessage:message]) {

return [_sessionCustomconfigcontentViewInsets:message];

}

//检查是不是聊天室文本消息

if ([selfisChatroomTextMessage:message]) {

// return [_chatroomTextConfig contentViewInsets:message];

}

//如果没有特殊需求,就走默认处理流程

return [supercontentViewInsets:model];

}

- (UIEdgeInsets)cellInsets:(NIMMessageModel *)model

{

NIMMessage *message = model.message;

//检查是不是聊天室消息

if (message.session.sessionType ==NIMSessionTypeChatroom) {

returnUIEdgeInsetsZero;

}

//如果没有特殊需求,就走默认处理流程

return [supercellInsets:model];

}

- (BOOL)shouldShowAvatar:(NIMMessageModel *)model

{

if ([selfisSupportedChatroomMessage:model.message]) {

returnNO;

}

return [supershouldShowAvatar:model];

}

- (BOOL)shouldShowLeft:(NIMMessageModel *)model{

if ([selfisSupportedChatroomMessage:model.message]) {

returnYES;

}

return [supershouldShowLeft:model];

}

- (BOOL)shouldShowNickName:(NIMMessageModel *)model{

if ([selfisSupportedChatroomMessage:model.message]) {

returnYES;

}

return [supershouldShowNickName:model];

}

- (CGFloat)nickNameMargin:(NIMMessageModel *)model{

if ([selfisSupportedChatroomMessage:model.message]) {

NSDictionary *ext = model.message.remoteExt;

NIMChatroomMemberType type = [ext[@"type"]integerValue];

switch (type) {

caseNIMChatroomMemberTypeManager:

caseNIMChatroomMemberTypeCreator:

return50.f;

default:

break;

}

return15.f;

}

return [supernickNameMargin:model];

}

- (NSArray *)customViews:(NIMMessageModel *)model

{

if ([selfisSupportedChatroomMessage:model.message]) {

NSDictionary *ext = model.message.remoteExt;

NIMChatroomMemberType type = [ext[@"type"]integerValue];

NSString *imageName;

switch (type) {

caseNIMChatroomMemberTypeManager:

imageName = @"chatroom_role_manager";

break;

caseNIMChatroomMemberTypeCreator:

imageName = @"chatroom_role_master";

break;

default:

break;

}

UIImageView *imageView;

if (imageName.length) {

UIImage *image = [UIImageimageNamed:imageName];

imageView = [[UIImageViewalloc] initWithImage:image];

CGFloat leftMargin =15.f;

CGFloat topMatgin =0.f;

CGRect frame = imageView.frame;

frame.origin =CGPointMake(leftMargin, topMatgin);

imageView.frame = frame;

}

return imageView ?@[imageView] :nil;

}

return [supercustomViews:model];

}

#pragma mark - misc

- (BOOL)isSupportedCustomMessage:(NIMMessage *)message

{

NIMCustomObject *object = message.messageObject;

return [objectisKindOfClass:[NIMCustomObjectclass]] &&

[_typesindexOfObject:NSStringFromClass([object.attachmentclass])] != NSNotFound;

}

- (BOOL)isSupportedChatroomMessage:(NIMMessage *)message

{

return message.session.sessionType == NIMSessionTypeChatroom &&

(message.messageType ==NIMMessageTypeText || [selfisSupportedCustomMessage:message]);

}

- (BOOL)isChatroomTextMessage:(NIMMessage *)message

{

return message.session.sessionType == NIMSessionTypeChatroom &&

message.messageObject ==NIMMessageTypeText;

}

以及自定义消息配置类: .h文件:

#import "NIMBaseSessionContentConfig.h"

@interface NTESSessionCustomContentConfig :NSObject<NIMSessionContentConfig>

@end

.m文件:

#import "NTESSessionCustomContentConfig.h"

#import "NTESCustomAttachmentDefines.h"

@interface NTESSessionCustomContentConfig()

@end

@implementation NTESSessionCustomContentConfig

- (CGSize)contentSize:(CGFloat)cellWidth message:(NIMMessage *)message

{

NIMCustomObject *object = message.messageObject;

NSAssert([object isKindOfClass:[NIMCustomObject class]],@"message must be custom");

id<NTESCustomAttachmentInfo> info = (id<NTESCustomAttachmentInfo>)object.attachment;

return [infocontentSize:message cellWidth:cellWidth];

}

- (NSString *)cellContent:(NIMMessage *)message

{

NIMCustomObject *object = message.messageObject;

NSAssert([object isKindOfClass:[NIMCustomObject class]],@"message must be custom");

id<NTESCustomAttachmentInfo> info = (id<NTESCustomAttachmentInfo>)object.attachment;

return [infocellContent:message];

}

- (UIEdgeInsets)contentViewInsets:(NIMMessage *)message

{

NIMCustomObject *object = message.messageObject;

NSAssert([object isKindOfClass:[NIMCustomObject class]],@"message must be custom");

id<NTESCustomAttachmentInfo> info = (id<NTESCustomAttachmentInfo>)object.attachment;

return [infocontentViewInsets:message];

}

@end

好了,到这里,自定义view和model类以及自定义cell布局类都设置完成了.

接下来我们实现自定义消息解析处理类: .h文件:

#import <Foundation/Foundation.h>

#import "NIMKit.h"

@interface NTESCustomAttachmentDecoder :NSObject<NIMCustomAttachmentCoding>

@end

.m文件:

#import "NTESCustomAttachmentDecoder.h"

#import "NTESCustomAttachmentDefines.h"

#import "NSDictionary+SLJSON.h"

#import "NTESSendShopGoodsAttachment.h"

#import "NTESChartletAttachment.h"

@implementation NTESCustomAttachmentDecoder

- (id<NIMCustomAttachment>)decodeAttachment:(NSString *)content

{

id<NIMCustomAttachment> attachment =nil;

NSData *data = [contentdataUsingEncoding:NSUTF8StringEncoding];

if (data) {

NSDictionary *dict = [NSJSONSerializationJSONObjectWithData:data

options:0

error:nil];

if ([dictisKindOfClass:[NSDictionaryclass]])

{

NSInteger type = [dictjsonInteger:CMType];

NSDictionary *data = [dictjsonDict:CMData];

switch (type) {

caseCustomMessageTypeChartlet:

{

attachment = [[NTESChartletAttachmentalloc] init];

((NTESChartletAttachment *)attachment).chartletCatalog = [datajsonString:CMCatalog];

((NTESChartletAttachment *)attachment).chartletId = [datajsonString:CMChartlet];

}

break;

caseCustomMessageSendShopGoods:

{

attachment = [[NTESSendShopGoodsAttachmentalloc] init];

((NTESSendShopGoodsAttachment *)attachment).headerImage = [datajsonString:CM_GOODS_IMG];

((NTESSendShopGoodsAttachment *)attachment).nameLabel = [datajsonString:CM_GOODS_NAME];

((NTESSendShopGoodsAttachment *)attachment).priceLabel = [datajsonString:CM_GOODS_PRICE]; }

default:

break;

}

attachment = [selfcheckAttachment:attachment] ? attachment :nil;

}

}

return attachment;

}

- (BOOL)checkAttachment:(id<NIMCustomAttachment>)attachment{

BOOL check =NO;

if ([attachmentisKindOfClass:[NTESSendShopGoodsAttachmentclass]]) {

NSString *headerImg = ((NTESSendShopGoodsAttachment *)attachment).headerImage;

NSString *shopNameLa = ((NTESSendShopGoodsAttachment *)attachment).nameLabel;

NSString *priceLa = ((NTESSendShopGoodsAttachment *)attachment).priceLabel;

check = shopNameLa.length&&priceLa.length&&headerImg.length ?YES : NO;

}elseif ([attachment isKindOfClass:[NTESChartletAttachmentclass]]) {

NSString *chartletCatalog = ((NTESChartletAttachment *)attachment).chartletCatalog;

NSString *chartletId =((NTESChartletAttachment *)attachment).chartletId;

check = chartletCatalog.length&&chartletId.length ?YES : NO;

}

return check;

}

@end

以上四部分处理我们都做完了.现在去入口类注册解析器和自定义cell配置:

// 注册自定义消息的解析器

[NIMCustomObjectregisterCustomDecoder:[NTESCustomAttachmentDecodernew]];

//注册 NIMKit自定义排版配置

[[NIMKitsharedKit] registerLayoutConfig:[NTESCellLayoutConfignew]];

在需要发送商品自定义消息的地方:

//自定义消息

-(void)sendManager:(UIButton *)btn

{

//隐藏topView

staticint a =80;

[UIViewanimateWithDuration:0.5animations:^{

CGRect rect =self.topView.frame;

rect.origin.y -=a;

self.topView.frame =rect;

} completion:^(BOOL finished) {

[self.topViewremoveFromSuperview];

}];

//发送自定义消息

self.attachment = [[NTESSendShopGoodsAttachmentalloc] init];

_attachment.messageDic =self.messageDict;

NIMMessage *message = [[NIMMessagealloc] init];

NIMCustomObject *customObject = [[NIMCustomObjectalloc] init];

customObject.attachment=_attachment;

message.messageObject = customObject;

[selfsendMessage:message];

}

在cell点击事件中,我们添加自定义消息类型判断(方法中文字为黑色部分).通过点击手势,进入其他界面.

#pragma mark ---------------- cell点击事件 ------------------

- (NSDictionary *)cellActions

{

staticNSDictionary *actions = nil;

staticdispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

actions = @{@(NIMMessageTypeImage) : @"showImage:",

@(NIMMessageTypeVideo) : @"showVideo:",

@(NIMMessageTypeLocation) :@"showLocation:",

@(NIMMessageTypeFile) : @"showFile:",

@(NIMMessageTypeCustom): @"showCustom:"};

});

return actions;

}

-(BOOL)onTapCell:(NIMKitEvent *)event

{

BOOL handle =[superonTapCell:event];

NSString *eventName = event.eventName;

if ([eventNameisEqualToString:NIMKitEventNameTapAudio])

{

//音频

[self.interactormediaAudioPressed:event.messageModel];

handle = YES;

}

elseif([eventNameisEqualToString:NIMKitEventNameTapContent]){

BOOL handle =NO;

NIMMessage *message = event.messageModel.message;

NSDictionary *actions = [selfcellActions];

NSString *value = actions[@(message.messageType)];

if (value) {

SEL selector =NSSelectorFromString(value);

NSLog(@"value ---- %@,%d",value,(selector && [selfrespondsToSelector:selector]));

if (selector && [selfrespondsToSelector:selector]) {

SuppressPerformSelectorLeakWarning([self performSelector:selector withObject:message]);

handle = YES;

}

}

}

elseif([eventNameisEqualToString:NIMKitEventNameTapLabelLink])

{

NSString *link = event.data;

[self.viewmakeToast:[NSStringstringWithFormat:@"tap link : %@",link]

duration:2

position:CSToastPositionCenter];

handle = YES;

}elseif ([eventName isEqualToString:SendCustomWithGoodsClick]){

//自定义商品注入

NIMCustomObject * customObject =(NIMCustomObject *)event.messageModel.message.messageObject;

id attachment =customObject.attachment;

NSString * goodsId =[attachment goodsAttaId];

//自定义商品注入

JKNewGoodsDetailVC * goodVC =[[JKNewGoodsDetailVC alloc]init];

//添加商品id

goodVC.goodsId = [goodsId intValue];

[self.navigationController pushViewController:goodVC animated:YES];

handle =YES;

}

// if (!handle) {

// NSAssert(0, @"invalid event ----哈哈哈!垃圾...崩溃了");

// }

return handle;

}

到此为止,我们的代码算是写完了!运行我们的模拟器!效果如下:

代码还不太完整.不过整体步骤和思路很清晰了.大家可以做个参考.如果有地方不明白.可以私聊我咨询.或者加入One Team:234713941 技术交流群

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。