iOS 环信 EaseUI 的使用一:可发送类似名片自定义的消息

Pod集成的EaseUI,我这里使用的是不带音视频的skd.(如果使用音视频版本请参考环信文档,但是后面具体操作基本一致)

打开cocoaPod(已安装的情况下,未安装的请自行百度安装) 然后cd到自己的项目工程下,

在pod中复制粘贴,(如果要指定版本,可以在更改后面的tag值,)

pod 'EaseUI', :git => 'https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git', :tag => '3.3.6'


这里主要讲述单聊(自定义名片消息和正常的聊天消息)和聊天列表的集成实现.

一:单聊

自定义一个viewController 继承环信EaseUI中的EaseMessageViewController聊天界面控制器.我这边起名:CahtWithPVControllerViewController.我们主要实现单聊中的类似于淘宝和商家交谈发送某个商品的情况:正常消息和自定义消息的实现:如图

iOS 环信 EaseUI 的使用一:可发送类似名片自定义的消息_第1张图片
iOS 环信 EaseUI 的使用一:可发送类似名片自定义的消息_第2张图片



在我们继承好的自定义控制中,我们主要分清两种情况,自己发送和对方发送,自己接收和对方接收,这些我们都是可以根据代理实现的.所以我们要设置代理,然后实现代理.代码如下

继承代理

- (void)viewDidLoad {

[super viewDidLoad];

self.showRefreshHeader = YES;

self.delegate= self;

self.dataSource = self;

}

实现原本的自有的方法

//会话界面的shua xin

- (void)tableViewDidTriggerHeaderRefresh

{

NSString*startMessageId =nil;

if ([self.messsagesSource count] > 0) {

startMessageId = [(EMMessage*)self.messsagesSource.firstObjectmessageId];

}

NSLog(@"startMessageID ------- %@",startMessageId);

[EMClient.sharedClient.chatManager asyncFetchHistoryMessagesFromServer:self.conversation.conversationId

conversationType:self.conversation.type

startMessageId:startMessageId

pageSize:10

completion:^(EMCursorResult*aResult,EMError*aError)

{

[super tableViewDidTriggerHeaderRefresh];

}];

}

先写到这里关键的代码在梳理完流程后在去写.



我在自定的CahtWithPVControllerViewController中为继承过来的tableView添加了一个头视图(根据项目需求来做,视图加在哪里都可以)就是下面这一块,

iOS 环信 EaseUI 的使用一:可发送类似名片自定义的消息_第3张图片

我的代码

- (void)configureGoodView {

UIView *bgV = [[UIView alloc] initWithFrame:CGRectMake(0, 10, kScreenWidth, 150)];

bgV.backgroundColor = [UIColor whiteColor];

UIImageView *imageV = [[UIImageView alloc] init];

imageV.frame=CGRectMake(15,15,80,80);

[imageVsd_setImageWithURL:[NSURL URLWithString:_goodImage] placeholderImage:[UIImage imageNamed:@"80"]];

[bgVaddSubview:imageV];

UILabel *titleLB = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(imageV.frame)+15, 15, kScreenWidth - CGRectGetWidth(imageV.frame) -30, 45)];

titleLB.font=kFont16;

titleLB.textColor=blackZiti;

titleLB.numberOfLines=0;

titleLB.text=_goodName;

[bgVaddSubview:titleLB];

UILabel *priceLB = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(imageV.frame)+15, CGRectGetMaxY(imageV.frame)- 30, kScreenWidth - CGRectGetWidth(imageV.frame) -30, 30)];

priceLB.font=kFont16;

priceLB.textColor = [UIColor redColor];

priceLB.text = [NSString stringWithFormat:@"¥%@",_goodPrice];

priceLB.numberOfLines=0;

[bgVaddSubview:priceLB];

UIButton *btn = [UIButton buttonWithType:(UIButtonTypeCustom)];

btn.frame=CGRectMake((kScreenWidth-100)/2,CGRectGetMaxY(imageV.frame)+15,100,30);

[btnsetTitle:@"发送宝贝" forState:(UIControlStateNormal)];

[btnsetTitleColor:erqiZiTColor forState:(UIControlStateNormal)];

btn.layer.masksToBounds = YES;

btn.titleLabel.font = kFont15;

btn.layer.cornerRadius = 35/2;

btn.layer.borderColor = erqiZiTColor.CGColor;

btn.layer.borderWidth = 0.8;

[btnaddTarget:self action:@selector(sendRecommendFriend) forControlEvents:(UIControlEventTouchUpInside)];

[bgVaddSubview:btn];

// [self tableViewDidTriggerHeaderRefresh];

self.tableView.tableFooterView = bgV;

}


在我们点击发送宝贝的时候要把这个宝贝发送给商家:类似于下图:

iOS 环信 EaseUI 的使用一:可发送类似名片自定义的消息_第4张图片

实现点击事件:

- (void)sendRecommendFriend{

[self sendTextMessage:@"商品链接" withExt:@{@"nickname":@"张三自己的名字",@"headimgurl":@"http://iamgename自己的头像",@"goodName":@"商品名字",@"goodPrice":@"商品价格",@"goodImage":@"商品图像",@"goodId":@"商品id"}];

//发送完成后把之前设置的tableFooterView置位空(根据需求来制定)

self.tableView.tableFooterView = nil;

}

这里我们用到EaseUI中的sendTextMessage这个方法,

- (void)sendTextMessage:(NSString*)text withExt:(NSDictionary*)ext;

第一个text是文本消息,这里我们用来作一个和其他消息区分的唯一标识,ext可以理解为消息体,是一个字典,用来存储想要发送的内容参数.在发送和接收端,我们可以根据text去找到ext,再根据自定义的消息cell去显示,具体如下






我们看到这条消息跟正常的聊天消息不一样,所以我们需要自定义一套cell来实现这些参数的显示:EaseUI本身有一套cell我们需要继承他们的cell以至于达到我们想要的目的.所以我们自定义一个继承EaseBaseMessageCell的cell 取名:IMChatBusinessCardCell,然后还需要针对EaseBubbleView写个分类,关联一些名片所需要的控件:取名IMChatBusinessCard   .( commend+n选择Objective-C File如下图)

iOS 环信 EaseUI 的使用一:可发送类似名片自定义的消息_第5张图片


这些完成以后开始写代码,因为在自定义的聊天cell里我们需要显示商品图片,商品名字和商品价格.

所以我们在EaseBubbleView+IMChatBusinessCard.h中写

// 商品图片

@property(strong,nonatomic)UIImageView*userHeaderImageView;

// 商品名字

@property (strong, nonatomic) UILabel *userNameLabel;

// 商品价格

@property (strong, nonatomic) UILabel *userPhoneLabel;

// 设置名片气泡

- (void)setupBusinessCardBubbleView;

// 更新名片间距

- (void)updateBusinessCardMargin:(UIEdgeInsets)margin;

// 设置约束

- (void)_setupConstraintsXX;


然后在EaseBubbleView+IMChatBusinessCard.m中我这里全部复制一下,你们用的时候把重复的和没用的去掉就可以了.

#import "EaseBubbleView+IMChatBusinessCard.h"

#import

staticchar_userHeaderImageView_;

staticchar_userNameLabel_;

staticchar_userPhoneLabel_;

@implementationEaseBubbleView (IMChatBusinessCard)

- (void)_setupConstraintsXX{

[self.marginConstraints removeAllObjects];

//userHeaderImageView

NSLayoutConstraint*userHeaderImageViewTopConstraint =

[NSLayoutConstraint constraintWithItem:self.userHeaderImageView

attribute:NSLayoutAttributeTop

relatedBy:NSLayoutRelationEqual

toItem:self.backgroundImageView

attribute:NSLayoutAttributeTop

multiplier:1.0

constant:10];

NSLayoutConstraint*userHeaderImageViewLeadingConstraint =

[NSLayoutConstraint constraintWithItem:self.userHeaderImageView

attribute:NSLayoutAttributeLeading

relatedBy:NSLayoutRelationEqual

toItem:self.backgroundImageView

attribute:NSLayoutAttributeLeading

multiplier:1.0

constant:10];

[self.marginConstraintsaddObject:userHeaderImageViewTopConstraint];

[self.marginConstraintsaddObject:userHeaderImageViewLeadingConstraint];

NSLayoutConstraint*userHeaderImageViewHeightConstraint =

[NSLayoutConstraint constraintWithItem:self.userHeaderImageView

attribute:NSLayoutAttributeHeight

relatedBy:NSLayoutRelationEqual

toItem:nil

attribute:NSLayoutAttributeNotAnAttribute

multiplier:0.0

constant:60];

NSLayoutConstraint*userHeaderImageViewWidthConstraint =

[NSLayoutConstraint constraintWithItem:self.userHeaderImageView

attribute:NSLayoutAttributeWidth

relatedBy:NSLayoutRelationEqual

toItem:nil

attribute:NSLayoutAttributeNotAnAttribute

multiplier:0.0

constant:60];

[self.userHeaderImageViewaddConstraint:userHeaderImageViewHeightConstraint];

[self.userHeaderImageViewaddConstraint:userHeaderImageViewWidthConstraint];

// userNameLabel

NSLayoutConstraint*userNameLabelWithMarginTopConstraint =

[NSLayoutConstraint constraintWithItem:self.userNameLabel

attribute:NSLayoutAttributeTop

relatedBy:NSLayoutRelationEqual

toItem:self.userHeaderImageView

attribute:NSLayoutAttributeTop

multiplier:1.0

constant:2];

NSLayoutConstraint*userNameLabelWithMarginRightConstraint =

[NSLayoutConstraint constraintWithItem:self.userNameLabel

attribute:NSLayoutAttributeTrailing

relatedBy:NSLayoutRelationEqual

toItem:self.backgroundImageView

attribute:NSLayoutAttributeTrailing

multiplier:1.0

constant:-self.margin.right];

NSLayoutConstraint*userNameLabelWithMarginLeftConstraint =

[NSLayoutConstraint constraintWithItem:self.userNameLabel

attribute:NSLayoutAttributeLeading

relatedBy:NSLayoutRelationEqual

toItem:self.userHeaderImageView

attribute:NSLayoutAttributeTrailing

multiplier:1.0

constant:10];

[self.marginConstraintsaddObject:userNameLabelWithMarginRightConstraint];

[self.marginConstraintsaddObject:userNameLabelWithMarginTopConstraint];

[self.marginConstraintsaddObject:userNameLabelWithMarginLeftConstraint];

// userPhoneLabel

NSLayoutConstraint*userPhoneLabelTopConstraint =

[NSLayoutConstraint constraintWithItem:self.userPhoneLabel

attribute:NSLayoutAttributeBottom

relatedBy:NSLayoutRelationEqual

toItem:self.userHeaderImageView

attribute:NSLayoutAttributeBottom

multiplier:1.0

constant:1];

NSLayoutConstraint*userPhoneLabelLeftConstraint =

[NSLayoutConstraint constraintWithItem:self.userPhoneLabel

attribute:NSLayoutAttributeLeading

relatedBy:NSLayoutRelationEqual

toItem:self.userNameLabel

attribute:NSLayoutAttributeLeading

multiplier:1.0

constant:0];

NSLayoutConstraint*userPhoneLabelRightConstraint =

[NSLayoutConstraint constraintWithItem:self.userPhoneLabel

attribute:NSLayoutAttributeTrailing

relatedBy:NSLayoutRelationEqual

toItem:self.backgroundImageView

attribute:NSLayoutAttributeTrailing

multiplier:1.0

constant:-self.margin.right];

[self.marginConstraintsaddObject:userPhoneLabelTopConstraint];

[self.marginConstraintsaddObject:userPhoneLabelLeftConstraint];

[self.marginConstraintsaddObject:userPhoneLabelRightConstraint];

[self addConstraints:self.marginConstraints];

NSLayoutConstraint *backImageConstraint = [NSLayoutConstraint constraintWithItem:self attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:0.0f constant:260];

[self.superviewaddConstraint:backImageConstraint];

}

#pragma mark - public

- (void)setupBusinessCardBubbleView{

// 头像

self.userHeaderImageView = [UIImageView new];

[self.userHeaderImageView setImage:[UIImage imageNamed:@"默认头像2"]];

self.userHeaderImageView.translatesAutoresizingMaskIntoConstraints = NO;

[self.backgroundImageView addSubview:self.userHeaderImageView];

// 昵称

self.userNameLabel = [UILabel new];

self.userNameLabel.font = [UIFont systemFontOfSize:15.0f];

self.userNameLabel.textColor = [UIColor lightGrayColor];

self.userNameLabel.translatesAutoresizingMaskIntoConstraints = NO;

self.userNameLabel.numberOfLines = 2;

[self.backgroundImageView addSubview:self.userNameLabel];

// 手机号

self.userPhoneLabel = [UILabel new];

self.userPhoneLabel.font = [UIFont systemFontOfSize:13.0f];

self.userPhoneLabel.textColor = [UIColor lightGrayColor];

self.userPhoneLabel.translatesAutoresizingMaskIntoConstraints = NO;

[self.backgroundImageView addSubview:self.userPhoneLabel];

[self _setupConstraintsXX];

}

- (void)updateBusinessCardMargin:(UIEdgeInsets)margin

{

if(_margin.top== margin.top&&_margin.bottom== margin.bottom&&_margin.left== margin.left&&_margin.right== margin.right) {

return;

}

_margin= margin;

[self removeConstraints:self.marginConstraints];

[self _setupConstraintsXX];

}

#pragma mark - getter and setter

- (void)setUserHeaderImageView:(UIImageView*)userHeaderImageView

{

objc_setAssociatedObject(self, &_userHeaderImageView_, userHeaderImageView, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (UIImageView*)userHeaderImageView

{

return objc_getAssociatedObject(self, &_userHeaderImageView_);

}

- (void)setUserNameLabel:(UILabel*)userNameLabel

{

objc_setAssociatedObject(self, &_userNameLabel_, userNameLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (UILabel*)userNameLabel

{

return objc_getAssociatedObject(self, &_userNameLabel_);

}

- (void)setUserPhoneLabel:(UILabel*)userPhoneLabel

{

objc_setAssociatedObject(self, &_userPhoneLabel_, userPhoneLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

}

- (UILabel*)userPhoneLabel

{

return objc_getAssociatedObject(self, &_userPhoneLabel_);

}

@end

这里设置完成后到IMChatBusinessCardCell.m中

也全部复制一下

#import "IMChatBusinessCardCell.h"

#import "EaseBubbleView+IMChatBusinessCard.h"

staticconstCGFloatkCellHeight =110.0f;

@implementationIMChatBusinessCardCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString*)reuseIdentifier model:(id)model{

    self= [superinitWithStyle:stylereuseIdentifier:reuseIdentifiermodel:model];

    if(self) {

        self.hasRead.hidden=YES;

        self.selectionStyle = UITableViewCellSelectionStyleNone;

    }

    return self;

}

- (BOOL)isCustomBubbleView:(id)model{

    return YES;

}

- (void)setCustomModel:(id)model{

    UIImage*image = model.image;

    if(!image) {

        [self.bubbleView.imageView sd_setImageWithURL:[NSURL URLWithString:model.fileURLPath] placeholderImage:[UIImage imageNamed:model.failImageName]];

    }else{

        _bubbleView.imageView.image = image;

    }

    if(model.avatarURLPath) {

        [self.avatarView sd_setImageWithURL:[NSURL URLWithString:model.avatarURLPath] placeholderImage:model.avatarImage];

    }else{

        self.avatarView.image = model.avatarImage;

    }

}

- (void)setCustomBubbleView:(id)model{

    [_bubbleView setupBusinessCardBubbleView];

    _bubbleView.imageView.image = [UIImage imageNamed:@"80"];

}

- (void)updateCustomBubbleViewMargin:(UIEdgeInsets)bubbleMargin model:(id)mode{

    [_bubbleView updateBusinessCardMargin:bubbleMargin];

    _bubbleView.translatesAutoresizingMaskIntoConstraints = YES;

    CGFloatbubbleViewHeight =84;// 气泡背景图高度

    CGFloatnameLabelHeight =15;// 昵称label的高度

    if(mode.isSender) {

        _bubbleView.frame =

        CGRectMake([UIScreenmainScreen].bounds.size.width-273.5, nameLabelHeight,213, bubbleViewHeight);

    }else{

        _bubbleView.frame=CGRectMake(55, nameLabelHeight,213, bubbleViewHeight);

    }

    // 这里强制调用内部私有方法

    [_bubbleView _setupConstraintsXX];

}

- (NSString*)cellIdentifierWithModel:(id)model{

    return NSStringFromClass([self class]);

}

- (CGFloat)cellHeightWithModel:(id)model{

    return kCellHeight;

}

- (void)setModel:(id)model{

    [supersetModel:model];

NSDictionary *ext = [[NSDictionary alloc]initWithDictionary:model.message.ext];

    //发送了商品信息的情况

    if(ext !=nil) {


    self.bubbleView.userNameLabel.text= ext[@"goodName"];

    self.bubbleView.userPhoneLabel.text = [NSString  stringWithFormat:@"¥%@",ext[@"goodPrice"]];

[self.bubbleView.userHeaderImageView sd_setImageWithURL:[NSURL URLWithString:ext[@"goodImage"]]];

    }


    _hasRead.hidden = YES;//名片消息不显示已读

}

- (void)layoutSubviews

{

    [super layoutSubviews];

    NSString*imageName =self.model.isSender?@"bai":@"lam";

    UIImage *image = self.model.isSender ? [[UIImage imageNamed:imageName] stretchableImageWithLeftCapWidth:30 topCapHeight:35] :

    [[UIImage imageNamed:imageName] stretchableImageWithLeftCapWidth:20 topCapHeight:35];

}

@end


然后我们回到自定义的聊天控制器CahtWithPVControllerViewController

导入刚才的类头文件

#import "IMChatBusinessCardCell.h"

#import "EaseBubbleView+IMChatBusinessCard.h"

我们需要实现- (UITableViewCell*)messageViewController:(UITableView*)tableView

cellForMessageModel:(id)messageModel;这个方法来显示我们自定义的cell

- (UITableViewCell*)messageViewController:(UITableView*)tableView

cellForMessageModel:(id)messageModel

{

if(messageModel.bodyType==EMMessageBodyTypeText&&

[[messageModeltext]hasPrefix:@"商品链接"]) {

NSString *CellIdentifier = [NSString stringWithFormat:@"%@", [NSDate dateTomorrow]];

IMChatBusinessCardCell*cell = (IMChatBusinessCardCell*)[tableViewdequeueReusableCellWithIdentifier:CellIdentifier];

if(cell ==nil) {

cell = [[IMChatBusinessCardCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:messageModel];

cell.selectionStyle = UITableViewCellSelectionStyleNone;

}

cell.model= messageModel;

returncell;

}

return nil;

}

然后更改一下自定义消息的高度

- (CGFloat)messageViewController:(EaseMessageViewController*)viewController

heightForMessageModel:(id)messageModel

withCellWidth:(CGFloat)cellWidth

{

NSDictionary*ext = messageModel.message.ext;

if([extobjectForKey:@"em_recall"]) {

return self.timeCellHeight;

}

if([[messageModeltext]hasPrefix:@"商品链接"]) {

return130;

}

return 0;

}

为显示cell消息赋值的时候我们需要实现- (id)messageViewController:(EaseMessageViewController*)viewController modelForMessage:(EMMessage*)message;这个方法.

- (id)messageViewController:(EaseMessageViewController*)viewController modelForMessage:(EMMessage*)message

{

id model =nil;

model = [[EaseMessageModel alloc] initWithMessage:message];

if(model.isSender) {//自己发送

if([_typeChatisEqualToString:@"store"]) {

if(message.ext!=nil&& [[message.extallKeys]containsObject:@"goodName"]) {

model.message.ext =@{@"nickname":[SingleUserInfoManage shareData].nickname,@"headimgurl":[SingleUserInfoManage shareData].im_headimgurl,@"goodName":message.ext[@"goodName"],@"goodPrice":message.ext[@"goodPrice"],@"goodImage":message.ext[@"goodImage"],@"goodId":message.ext[@"goodId"]};

}else{

model.message.ext= @{@"headimgurl":[SingleUserInfoManage shareData].im_headimgurl,@"nickname":[SingleUserInfoManage shareData].nickname};

}

//头像

model.avatarURLPath = [SingleUserInfoManage shareData].im_headimgurl;

//昵称

model.nickname = [SingleUserInfoManage shareData].nickname;

//头像占位图

model.avatarImage = [UIImage imageNamed:@"默认头像2"];

}else{

if(message.ext!=nil&&[[message.extallKeys]containsObject:@"goodName"]) {

model.message.ext =@{@"nickname":[SingleUserInfoManage shareData].nickname,@"headimgurl":[SingleUserInfoManage shareData].im_headimgurl,@"goodName":message.ext[@"goodName"],@"goodPrice":message.ext[@"goodPrice"],@"goodImage":message.ext[@"goodImage"],@"goodId":message.ext[@"goodId"]};

}else{

model.message.ext= @{@"headimgurl":[SingleUserInfoManage shareData].im_headimgurl,@"nickname":[SingleUserInfoManage shareData].nickname};

}

//头像

model.avatarURLPath = [SingleUserInfoManage shareData].im_headimgurl;

//昵称

model.nickname = [SingleUserInfoManage shareData].nickname;

//头像占位图

model.avatarImage = [UIImage imageNamed:@"默认头像2"];

}

}else{//对方发送

//头像占位图

model.avatarImage = [UIImage imageNamed:@"默认头像2"];

//头像avatar

model.avatarURLPath= message.ext[@"headimgurl"];

//昵称

model.nickname=  message.ext[@"nickname"];

}

returnmodel;

}

(附加)如果我们需要点击这个自定义消息,可以实现

我这里是跳转到商品详情:

//消息的点击

- (BOOL)messageViewController:(EaseMessageViewController*)viewController

didSelectMessageModel:(id)messageModel {

if(messageModel.bodyType==EMMessageBodyTypeText&&

[[messageModeltext]hasPrefix:@"商品链接"]) {

NSDictionary *ext = [[NSDictionary alloc]initWithDictionary:messageModel.message.ext];

FenLeiDDetailViewController *vc = [[FenLeiDDetailViewController alloc] init];

vc.goodsID= ext[@"goodId"];

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

}

return YES;

}

我们在这里面做很多判断主要用来区分正常消息和自定义消息,自定义消息(我们在发送消息的时候有一个text作为自定义消息的标识)由我们自定义的控件去完成.正常的消息由环信的控件去完成.这里面可能有一些我自己项目中用到你们用不到的东西,你们可以检查一下代码,修改成自己所需要的,有错误的调整一下.原理和代码大概就是这样.

最后附上demo,由于是从项目中抽取出来的,所以有点乱,但是还是能看的,哈哈,

链接:https://pan.baidu.com/s/10HPg3J2bh42VPs7B0mkZVA 密码:eijz

你可能感兴趣的:(iOS 环信 EaseUI 的使用一:可发送类似名片自定义的消息)