美文网首页程序员
iOS 环信 EaseUI 的使用一:可发送类似名片自定义的消息

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

作者: 嗯嗯大葱 | 来源:发表于2018-04-11 15:20 被阅读0次

    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.我们主要实现单聊中的类似于淘宝和商家交谈发送某个商品的情况:正常消息和自定义消息的实现:如图


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

    继承代理<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添加了一个头视图(根据项目需求来做,视图加在哪里都可以)就是下面这一块,

    我的代码

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

    }


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

    实现点击事件:

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


    这些完成以后开始写代码,因为在自定义的聊天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 的使用一:可发送类似名片自定义的消息

        本文链接:https://www.haomeiwen.com/subject/lnnjvxtx.html