iOS 環信 EaseUI 的使用一:可傳送類似名片自定義的訊息

weixin_34320159發表於2018-04-11

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.我們主要實現單聊中的類似於淘寶和商家交談傳送某個商品的情況:正常訊息和自定義訊息的實現:如圖

3020765-0c6be29de6623d04.PNG
3020765-4cf2f0a100341a29.PNG



在我們繼承好的自定義控制中,我們主要分清兩種情況,自己傳送和對方傳送,自己接收和對方接收,這些我們都是可以根據代理實現的.所以我們要設定代理,然後實現代理.程式碼如下

繼承代理<EaseMessageViewControllerDataSource,EaseMessageViewControllerDelegate>

- (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新增了一個頭檢視(根據專案需求來做,檢視加在哪裡都可以)就是下面這一塊,

3020765-dfca744f2faea20b.png

我的程式碼

- (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;

}


在我們點選傳送寶貝的時候要把這個寶貝傳送給商家:類似於下圖:

3020765-286a349bce9a19e2.png

實現點選事件:

- (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如下圖)

3020765-c3a06f98aaeb9013.png
3020765-535ced30003f9ffb.png


這些完成以後開始寫程式碼,因為在自定義的聊天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

相關文章