美文网首页iOS自定义控件及相关iOS之环信Demo3.0分析iOS备忘录
环信源码分析---自定义消息工具条和表情键盘以及集成环信遇到的坑

环信源码分析---自定义消息工具条和表情键盘以及集成环信遇到的坑

作者: Code_Ninja | 来源:发表于2016-03-08 18:19 被阅读7360次

    今天看了下环信SDK聊天模块下封装的自定义消息工具条以及表情键盘,了解了下iOS自带表情的转码。顺带记录下集成环信SDK遇到的坑。

    一、DXMessageToolBar工具条的封装

    DXMessageToolBar是加在聊天页面底部的消息工具条,其负责控制四个控件:

    1、录音视图DXRecordView
    2、输入文本框XHMessageTextView
    3、表情键盘DXFaceView
    4、更多视图DXChatBarMoreView

    DXMessageToolBar不仅要控制这四个UIView之间的切换,负责正确改变视图的位置与大小,还要将一系列的动作事件通过委托传到聊天页面控制器ChatViewController中去处理。

    DXRecordView是录制音频的时候展示的视图,通过不断检测音量大小来展示不同的UIImage从而达到动态效果。

    XHMessageTextView是继承自UITextView的,其中实现了自定义placeHolder的颜色,由于修改placeHolder是私有方法,因此这里换了种方式实现,那就是通过重写drawRect:方法,在其中将placeHolder绘制到UITextView上面。

    DXFaceView表情键盘,它上面加了FacialView。FacialView上面放置了一些列的UIButton,UIButton的标题设置为iOS自带的表情。

    DXChatBarMoreView更多视图,上面添加从相册选择照片,调用相机拍摄照片等按钮。

    二、表情键盘的封装

    表情键盘上放置了一些iOS自带的表情,而且在最后加了一个发送按钮和一个删除按钮,如图:

    环信表情键盘

    点击对应的表情,将表情字符串添加到文本框中。点击删除按钮通过委托调用了DXMessageToolBar的方法,其实现方式:

    - (void)selectedFacialView:(NSString *)str isDelete:(BOOL)isDelete
    {
        NSString *chatText = self.inputTextView.text;
        
        if (!isDelete && str.length > 0) {
            self.inputTextView.text = [NSString stringWithFormat:@"%@%@",chatText,str];
        }
        else {
            if (chatText.length >= 2)
            {
                NSString *subStr = [chatText substringFromIndex:chatText.length-2];
                if ([(DXFaceView *)self.faceView stringIsFace:subStr]) {
                    self.inputTextView.text = [chatText substringToIndex:chatText.length-2];
                    [self textViewDidChange:self.inputTextView];
                    return;
                }
            }
            
            if (chatText.length > 0) {
                self.inputTextView.text = [chatText substringToIndex:chatText.length-1];
            }
        }
        
        [self textViewDidChange:self.inputTextView];
    }
    
    

    由此可见一个表情字符串占两个字符的长度,所以要在点击删除按钮之后判断文本框当前字符串的末尾处是否是表情。

    三、iOS自带表情的转码

    每个表情都有它自己的编码,通过编码可以拿到它对应的表情字符串:

    #import <Foundation/Foundation.h>
    
    #define MAKE_Q(x) @#x
    #define MAKE_EM(x,y) MAKE_Q(x##y)
    
    #pragma clang diagnostic push
    #pragma clang diagnostic ignored "-Wunicode"
    #define MAKE_EMOJI(x) MAKE_EM(\U000,x)
    #pragma clang diagnostic pop
    
    #define EMOJI_METHOD(x,y) + (NSString *)x { return MAKE_EMOJI(y); }
    #define EMOJI_HMETHOD(x) + (NSString *)x;
    #define EMOJI_CODE_TO_SYMBOL(x) ((((0x808080F0 | (x & 0x3F000) >> 4) | (x & 0xFC0) << 10) | (x & 0x1C0000) << 18) | (x & 0x3F) << 24);
    
    /*!
     @class
     @brief iOS内置表情编码处理类
     */
    @interface Emoji : NSObject
    
    /*!
     @method
     @brief unicode编码转换为iOS内置表情字符串
     @discussion
     @param code iOS内置表情对应的unicode编码值
     @result iOS内置表情字符串
     */
    + (NSString *)emojiWithCode:(int)code;
    
    /*!
     @method
     @brief 获取所有iOS内置表情
     @discussion
     @result iOS表情字符串数组
     */
    + (NSArray *)allEmoji;
    @end
    
    #import "Emoji.h"
    #import "EmojiEmoticons.h"
    
    @implementation Emoji
    + (NSString *)emojiWithCode:(int)code {
        int sym = EMOJI_CODE_TO_SYMBOL(code);
        return [[NSString alloc] initWithBytes:&sym length:sizeof(sym) encoding:NSUTF8StringEncoding];
    }
    + (NSArray *)allEmoji {
        NSMutableArray *array = [NSMutableArray new];
        [array addObjectsFromArray:[EmojiEmoticons allEmoticons]];
        return array;
    }
    @end
    
    

    这里拿表情编码做一系列运算,然后传入[[NSString alloc] initWithBytes:&sym length:sizeof(sym) encoding:NSUTF8StringEncoding];生成对应的字符串的运算方法暂时没找到解释,没搞清楚运算原理。若哪位大神看到出处,敬请告知!

    四、集成环信遇到的坑

    1、显示用户头像和昵称

    环信默认不显示头像和昵称,如果要显示头像,需要自己实现。这里要实现显示头像和昵称,需要发消息的时候在ext这个扩展字段中加入和Android约定好的字段,在接收到消息的时候将这些字段保存到本地数据库中。

    这里特别需要注意的一点是:在读取本地数据库的时候,是通过chatter来匹配的话,记得环信的chatter在保存的时候都做了小写处理。所以,在数据库中匹配的时候,最好是大小写不敏感的匹配方式:

    NSString *sql = [NSString stringWithFormat:@"select * from %@ 
    where upper(chatter)=upper('%@')",_tbName,chatter];
    

    2、自定义推送内容

    环信默认推送内容是“你有一条新的消息”,如果要自定义内容,需要在在ext扩展字段中添加以下字段:

    @"em_apns_ext":@{                           
    @"em_push_title":文本内容
                     },
    

    3、发送用户信息给客服

    如果要在用户跟客服聊天时能在客服后台看到当前用户的一些基本信息,需要在ext扩展字段中添加以下字段(比如需要用户手机号码和名字):

    @"weichat":@{
        @"visitor":@{
           @"phone":userPhone,
           @"userNickname":userNickName,
            }
       },
    

    4、发送用户轨迹给客服

    如果要在用户点击客服咨询时,比如是点击职位下面的咨询,想将当期职位的信息发给客服,那就是环信的发送用户轨迹信息。这个时候在进入聊天页面时需要单独处理,自动发送一个自己封装的信息:

    -(void)sendJobInfo:(YLJob *)aJob
    {
        NSMutableDictionary *ext = [NSMutableDictionary dictionary];
        NSDictionary *msgtype = @{@"track":@{@"title":aJob.title?:@"",
                                             @"item_url":aJob.link?:@""}};
        [ext setObject:msgtype forKey:@"msgtype"];
        
        EMChatText *text = [[EMChatText alloc] initWithText:[NSString stringWithFormat:@"我想咨询 %@",aJob.title?:@""]];
        EMTextMessageBody *body = [[EMTextMessageBody alloc] initWithChatObject:text];
        EMMessage *message = [[EMMessage alloc] initWithReceiver:_chatter bodies:[NSArray arrayWithObject:body]];
        message.ext = ext;
        [[EaseMob sharedInstance].chatManager asyncSendMessage:message progress:nil];
        
    }
    

    这里只是简单的使用了环信已经封装好的文本消息的接口,并且在聊天页面的展示方式也将是纯文本的方式Cell的展现方式。如果要以其他样式的Cell展示,需要自定义Cell,并且在展示的时候根据ext中的字段来判断是否是这种自定义消息。

    其他具体可用字段名称,请登录环信官网查看官方文档。

    参考:
    以下是Emoji的表情编码对照表:
    1、Emoji Unicode Tables

    相关文章

      网友评论

      • 小北风sky:感谢分享,环信替换表情的坑觉得好深……
      • 小伙eryayayayaya:显示用户头像和昵称能说在细点么。我这是接手别人的代码,不知道怎么改、写
        Code_Ninja:@小伙eryayayayaya 你先找到发消息和接受消息这两个地方,在发消息的时候会有个封装EMMessage对象的过程,EMMessage有个ext属性,专门用来存放用户自定义数据字段的。比如和安卓客户端约定好用户头像用avator来表示,那么在发消息的时候将avator字段存放在ext中传给彼此。同理,在接受消息的地方,从ext属性中拿avator字段即可。
      • 走着走着就会敲代码了:表示菜鸟看不懂,能说清楚点吗 :joy: 要修改哪里才可以?
        Code_Ninja:@shinephe 应该是可以的,最新版的环信SDK里面已经做了几套表情了(就是自定义图片),你可以去看下最新的环信SDK的代码。目前我们项目中还使用的老版本的SDK。
        IAMCifi:@Code_Ninja 你好 你这边写的表情键盘 可以发自定义图片吗 环信用的是iOS自带的Emoji
        Code_Ninja:@走着走着就会敲代码了 什么修改哪里?
      • 菩提树下本无树:我想问下博主,是否碰到过环信的消息录音的按钮经常会按不上的问题
        5dc048960049:在当前controller下重写
        - (UIRectEdge)preferredScreenEdgesDeferringSystemGestures{
        return UIRectEdgeBottom;
        }
        5dc048960049:我也遇到了,请问层主解决了吗?我试过是录音键太靠近屏幕底部了,但是位置不变的情况下要怎么解决按钮的延时呢
        Code_Ninja:@Reddick 没有遇到过
      • 纪叙:思路很清晰,作为环信的使用者,更是多了一番感悟,良心博客
        Code_Ninja:@纪叙 :grin:

      本文标题:环信源码分析---自定义消息工具条和表情键盘以及集成环信遇到的坑

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