美文网首页ios 知识点三方管理iOS开发新发现
iOS 集成环信(会话列表,聊天,昵称头像设置,自定义cell)

iOS 集成环信(会话列表,聊天,昵称头像设置,自定义cell)

作者: MonStar丶 | 来源:发表于2017-02-22 15:10 被阅读4700次

    一、环信SDK的集成

    0.先附一张项目聊天界面的截图,昵称和头像,还有自定义cell都有,会话列表就不贴图了,跟平时我们用QQ 、微信差不多

    1.去环信官网下载iOS版的SDK ,下载地址:环信iOS_SDK下载地址  ,接口文档地址:环信iOS_SDK集成文档

    2.按照接口文档一步一步将环信SDK集成到项目中,制作证书、添加依赖... 这些就不赘述了,官网的文档十分详细,这里我就讲一些注意点

    集成环信SDK过程可能遇到的一些情况和解决办法:

    (1)环信用到的第三方框架有:MWPhotoBrowser、MJRefresh、MBProgressHUD、SDWebImage(环信是自己在SDWebImage里面加一些功能并命名为:EMSDWebImage),所以你需要把跟你项目相同的框架删除一个,可以删除自己的或者删除环信的。其中SDWebImage,个人建议删除环信的EMSDWebImage,然后编译,这个时候肯定是编译失败,出现失败的原因是:少了一些sd里面的头文件和一些方法找不到,你直接将头文件删除,换成SDWebImage的,方法也是替换成SDWebImage的就行了

    (2)可能遇到的情况 :编译的时候报 "could not build module 'UIKit'" 或者是“could not build module 'Foundation'”,这种情况就是 你的pch 文件里,你导的头文件 不是包在  #ifdef __OBJC__    #endif  里面

    到此,如果你是严格按照官方文档的步骤一步不落的集成的话,应该是不会有什么问题的,是可以正常编译运行的。

    二、账号的登录

    1.看你们项目的要求,笔者是在自己app登录的时候,也把环信账号登录(登录的用户名和密码规则看你们后台是怎么配置的)。环信SDK是有自动登录的功能的,所以尽管用户杀死app后,再次启动app时,不需要再次进入登录界面再次登录

    环信账号登录

    2.账号登录的异常情况,比如说这个环信账号在别的地方登录了,那么就会出现登录失效,链接不到服务器的情况。这个时候环信提供了方法和属性来判断。 这属性和方法的回调是在EMClientDelegate协议里面的,在你的控制器里面遵守协议就可以

    通过属性来判断登录状态

    这是环信账号在你其他地方登录的时候的回调方法:

    账号在其他地方登录

    三、会话列表

    1.集成会话列表功能也十分简单的,首先新建一个控制器继承 EaseConversationListViewController,在viewDidLoad里面 设置delegate和dataSource遵守EaseConversationListViewControllerDelegate、EaseConversationListViewControllerDataSource协议,并加上 [self  tableViewDidTriggerHeaderRefresh]; 这句代码(首次进入刷新数据)。

    2.会话列表实时显示未读消息。也就是说在会话列表界面的时候,有人发消息过来了,发消息来的那个人的头像要有一个红色的数字,并显示未读消息数量,想要这个功能的话,就要遵守EMChatManagerDelegate 协议,并设置代理 [[EMClientsharedClient].chatManageraddDelegate:selfdelegateQueue:nil]; ,这个时候如果有消息来了,就会走消息的回调方法,在方法里面刷新界面即可。 下面的 refreshAndSortView 方法是刷新内存中的消息

    收到消息的回调,刷新界面

    3.最后一条消息的显示格式:在你的控制器里面添加下面代码 :

    - (NSAttributedString*)conversationListViewController:(EaseConversationListViewController*)conversationListViewController

    latestMessageTitleForConversationModel:(id)conversationModel

    {

    NSString*latestMessageTitle =@"";

    EMMessage*lastMessage = [conversationModel.conversationlatestMessage];

    if(lastMessage) {

    EMMessageBody*messageBody = lastMessage.body;

    switch(messageBody.type) {

    caseEMMessageBodyTypeImage:{

    latestMessageTitle =@"[图片]";

    }break;

    caseEMMessageBodyTypeText:{

    //表情映射。

    NSString*didReceiveText = [EaseConvertToCommonEmoticonsHelper

    convertToSystemEmoticons:((EMTextMessageBody*)messageBody).text];

    latestMessageTitle = didReceiveText;

    if([lastMessage.extobjectForKey:MESSAGE_ATTR_IS_BIG_EXPRESSION]) {

    latestMessageTitle =@"[动画表情]";

    }

    }break;

    caseEMMessageBodyTypeVoice:{

    latestMessageTitle =@"[音频]";

    }break;

    caseEMMessageBodyTypeLocation: {

    latestMessageTitle =@"[位置]";

    }break;

    caseEMMessageBodyTypeVideo: {

    latestMessageTitle =@"[视频]";

    }break;

    caseEMMessageBodyTypeFile: {

    latestMessageTitle =@"[文件]";

    }break;

    default: {

    }break;

    }

    }

    NSMutableAttributedString*attStr = [[NSMutableAttributedStringalloc]initWithString:latestMessageTitle];

    returnattStr;

    }

    3.如果需要加搜索功能的话,就去官方的demo里面 拷贝以下文件:

    搜索功能需要的文件

    在控制器里面遵守 EMSearchControllerDelegate协议,把demo里面的这三个方法里面的东西拷贝过来,删减掉一些不需要的代码就行了

    搜索功能需要添加的方法

    4.会话列表点击事件:

    会话列表点击事件跳转到聊天界面

    四、聊天功能

    1.新建一个控制器,继承 EaseMessageViewController ,遵守EaseMessageViewControllerDelegate、EaseMessageViewControllerDataSource协议,设置delegate和dataSource 即可

    2.删除底部更多菜单按钮,如果你不需要里面的视频通话、语音通话等功能的话,可以删除按钮

    删除底部更多菜单的按钮

    当然,你也可以自己添加按钮并设置图片。甚至可以去掉环信自带的更多菜单,添加自己自定义的。相信大多数人还是不要自定义的,这里就不把添加按钮和设置自定义更多菜单的方法赘述了,需要的可以去官方文档查看,那里有详细的讲解。

    3.如果在聊天界面点击头像需要跳转到该用户的个人信息界面或者其他界面的话,实现下面的方法添加跳转的方法即可:

    点击头像跳转到个人信息界面

    到此,即时通讯的 会话列表和聊天功能就已经实现了,就是一些UI 细节的调整了,比如,头像设置成自己的用户体系的头像,昵称设置成自己用户体系的昵称,下面我们来讲讲怎么实现头像和昵称的设置

    五、昵称和头像的设置

    1.先简述下设置昵称和头像功能的实现方式:在用户发送消息的时候,在消息里面添加一些扩展消息,以此将消息发送者的昵称和头像附带在消息里面发送过去,接受消息的人,通过消息里面的扩展消息(也就是昵称和头像)来将昵称和头像设置到界面上

    2.先找到发消息的方法,在发消息方法里面加扩展消息就可以不需要每次都去调他的发消息方法把扩展消息附带出去。所以,在环信的 EaseMessageViewController 里面的_sendMessage:方法里将发消息者的昵称和头像附带在扩展消息里面。 顺便提一下:不管是发送文本消息还是图片消息,语音消息都是会走该方法的。所以在登录的时候应该调你们项目中获取个人信息的接口,将昵称和头像存储起来,并且在跟换头像和昵称地方跟新存储的昵称和头像。

    在发送消息方法里面将用户自己的头像和昵称附带在消息扩展里面

    3.然后再聊天控制器里面实现下面的方法,将昵称和头像显示出来

    设置昵称和头像

    4.会话列表设置昵称和头像,需要注意的是,在用户第一次和某个人聊天发消息的时候,在会话列表是无法从消息扩展里面拿到发给消息的那个人的昵称和头像的,所以你需要存储聊天对象的昵称和头像,在你点击进入聊天页面的时候。

    会话列表设置昵称和头像

    到此,昵称和头像我们就已经可以设置完成了。

    六、自定义聊天Cell

    1.新建UITableViewCell文件,继承 EaseBaseMessageCell 。为了方便阅读者阅读无障碍,笔者就将自定义cell的所有代码 以截图的形式讲解。

    2.设置缓存cell的标识符,并添加子控件。

    添加子控件 设置缓存cell的标识符

    3.设置气泡和头像

    设置气泡背景和头像

    4.添加子控件

    添加子控件 添加自定义控件的约束

    5.在气泡里面添加label 以显示消息

    在气泡里面添加label以显示消息

    6.跟新气泡约束,设置气泡的frmae

    跟新气泡约束,设置气泡frame

    到此,自定义cell 就已经全部完成了。下面是在聊天控制器里面添加自定义cell和计算高度

    7.添加自定义的cell,如果是部分显示自定义的cell,部分是不需要显示自定的cell的时候,可以根据扩展消息来判断

    添加自定义的cell

    8.设置cell的高度

    设置cell的高度

    到此,自定义cell并显示自定义cell的功能已完成

    七、远程推送和本地通知

    1.首先需要知道的是:只有在app杀死的时候才会走远程推送,其他时候走本地通知。也就是说,app在后台的时候是走本地通知的,app在被用户杀死的时候才会走远程推送。

    2.远程推送(这里就讲一些细节注意点,代码的话,可以去拷贝官方demo,不管是远程推送还是本地通知都写的很清晰明了):

    (1)app在没有被杀死的时候,收到远程推送,在- (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo有回调,如果app被杀死了用户是点击了通知启动程序的是不会走上面的 didReceiveRemote......方法的而是走- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions,所以你需要在该方法里面根据launchOptions里面是否有UIApplicationLaunchOptionsRemoteNotificationKey 这个key来判断是不是收到了远程推送点击通知启动程序的,然后在里面添加跳转代码,如:

    根据key来判断是不是点击通知启动程序的

    (2)远程推送APNs需要配置推送证书,可以参考官方文档来配置,制作推送证书文档地址:制作推送证书

    2.本地推送

    (1)注册本地通知:在application didFinishLaunchingWithOptions方法里面注册本地通知,iOS 8以后需要自己注册本地通知

    (2)使用UNUserNotificationCenter发送本地通知需要注意这个方法是iOS 10 才有的方法,所以需要适配判断,否则iOS 10以下系统的用户会闪退。

    (3)关于接受到通知,用户点击通知启动程序的回调看下面的截图

    关于用户点击通知启动程序的回调方法解析

    如果文章中有什么错误或者更好的实现方式,欢迎各位留言指点,谢谢~

    相关文章

      网友评论

      • 招牌猪:楼主给个demo 可以吗? wangwenfa2008@qq.com
      • 9岁就很6:楼主可否提供下demo 。+1
      • 番茄炒西红柿啊:嗯,刚好最近在弄这个,谢谢分享
      • 67f75bf93352:大神,消息列表的头像设置那里,获取最后一条消息的扩展信息给头像赋值,那样头像会一直变啊,A给B发消息,B回复了一下,A再回复的话,那头像又变成A的了,应该一直是B啊,
        67f75bf93352:大神不用回复了,是我看错了,:grin:
        67f75bf93352:求回复
      • 请叫我小白同学:你好,我按照你所说的方式,把环信的EMSDWebImage的框架删除,替换SDWeblmage的,但是再替换方法过程中,找不到与emsdweblimg的对应的方法,就好比环信封装中的MWPhoto类中的downloadImageWithURL方法,找不到对应替换的,博主是如何决解这个问题的?:flushed:
        请叫我小白同学:@MonStar丶 谢谢指点,已经解决
        MonStar丶:@阿阿小白啊 你看看 环信的SDWebImage 和你自己项目中的SDWebImage 版本是不是一样的,你的版本更低,那就把你的版本替换成新的版本,你的更高的话,就跳进去看看环信的EMSDWebImage 这个方法是实现了什么功能,你把他的方法拷贝到 SDWebImage里面
      • F麦子:楼主能否给一下demo.谢谢
        MonStar丶:@X堇色 我已经不用环信了,是用我们公司自己团队写的一套即时通讯,所以没有demo 了
      • F麦子:大哥,如果对方修改了头像,然后给你发消息时,聊天界面同一个人会有不同的头像啊,这个怎么处理
      • 鸢尾嵌宇:为什么我自定义了单元格,之后,那个“已读”的提示就没有了呢?跪求:heart:
        鸢尾嵌宇:@MonStar丶 我总感觉是环信那边返回的isMessageRead是0,(我看里面有个EaseMessage,环信返回的一个isReadAcked就是0),
        /****
        我指定头像henicheng
        - (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
        modelForMessage:(EMMessage *)message
        {

        NSLog(@"-%u--",message.isReadAcked);

        //用户可以根据自己的用户体系,根据message设置用户昵称和头像
        id<IMessageModel> model = nil;
        model = [[EaseMessageModel alloc] initWithMessage:message];
        // model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];//默认头像
        if (model.isSender) {
        model.avatarURLPath = [[NSUserDefaults standardUserDefaults]objectForKey:@"headurl"];
        }else{
        model.avatarURLPath = self.frinendAvatar;

        }
        // model.isMessageRead = message.isRead;
        return model;
        }

        ****/

        /****
        自定义单元格
        - (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id<IMessageModel>)model
        {
        //样例为如果消息是文本消息显示用户自定义cell
        if (model.bodyType == EMMessageBodyTypeText || model.bodyType == EMMessageBodyTypeVoice || model.bodyType == EMMessageBodyTypeImage || model.bodyType == EMMessageBodyTypeLocation) {

        NSString *CellIdentifier = [LiaoTianCell cellIdentifierWithModel:model];
        //CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell
        LiaoTianCell *cell = (LiaoTianCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
        cell = [[LiaoTianCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:model];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        }
        cell.model = model;
        // cell.delegate = self;
        return cell;
        }
        return nil;
        }
        ***/

        跟您写的有哪里不一样吗?
        MonStar丶:查看UI层级关系的工具,查看不了hidden了的控件,但是可以很清楚看到有多少个控件(没有hidden)的,跟打印出来的cell 子控件个数对比,就知道是否把“已读”label ,添加到cell里了
        MonStar丶:只要是继承了 EaseBaseMessageCell,就会有已读的提示,你用 EaseMessageModel 的isMessageRead 属性看看,是否是已读。或者你打印一下,cell的子控件个数,配合Xcode 查看UI层级关系的工具,看看这个“已读”label,有没有加到cell里面去
      • MonStar丶:@晨曦景雪 你实现了cellforMessage方法了吗
        MonStar丶:那是在 .m里实现吧
        晨曦景雪:实现了啊 在#import "ChatViewController.h" 实现的 不走这个方法
      • 晨曦景雪:- (UITableViewCell *)messageViewController:(UITableView *)tableView
        cellForMessageModel:(id<IMessageModel>)messageModel 自定义这个方法不掉用如何解决
      • _流_沙_:楼主,你的会话列表中的本地化后存储数据的字典更新一下可以吗
      • 乂滥好人:楼主辛苦,对显示会话列表头像与昵称实在是不会,能否详细指点一下?谢谢了
        MonStar丶:@X堇色 1.所有发起的会话都自己建数据库,将对方的头像地址缓存到本地(最好用手机号或者对方的 id 来做key,只要是唯一的不会重复就行,实在拿不到就用nickname吧)
        2.在messageViewController:(EaseMessageViewController *)viewController
        modelForMessage:(EMMessage *)message里面 加个判断,如果从消息扩展里面取的头像跟自己本地不一致的时候,就需要先将新的头像缓存,并替换旧头像,并且需要刷新tableView 。 设头像的时候就用自己写好的根据 id 获取头像 如:[[HXUserInfoMang share] getImageUrlWithID:self._id] 来设置头像就行了

        注意:messageViewController:(EaseMessageViewController *)viewController
        modelForMessage这个方法,是有多少行就会调多少次,自己发一条消息就是有多少行调几次,别人发了一条消息过来就只会调一次,所以,你要在判断对方头像变化了的时候,刷新tableView ,不然还是会出现头像不一致
        MonStar丶:@X堇色 你的环信这版本的app 发版了吗? 没有发版的话就好解决
        F麦子:你好,我想问,如果两个人正在聊天,突然对方设置了新头像,再给你发消息时你这边她的头像会显示不一样,也就是现在对方的头像跟聊天窗口上面几天不同步,你解决了吗?有没有办法?搞了好久天了,不知道咋办,我的qq:1790462158,谢谢
      • feng_dev:超厉害的。
      • 別來無恙錒:楼主。能否提供一下 自定义Cell的demo。 QQ:1832525948 感谢🙏
        MonStar丶:@e2a5c6215897 我没有写demo ,你可以参考官方的demo 中,红包那块,那个就是自定义cell ,有不懂的可以问环信的在线技术客服
      • xiaowu0125:楼主少写了一个方法
        // 实时接收消息
        -(void)conversationListDidUpdate:(NSArray *)aConversationList{

        [self tableViewDidTriggerHeaderRefresh];
        }
        MonStar丶:@xiaowu0125 受教了,多谢。:blush:
        xiaowu0125:这个方法是会话列表刚开始没有这条记录,接收到消息时,调用的
        MonStar丶:@xiaowu0125 我实现了 messageDidRecevice方法,在这个方法里面刷新也是可以的。
      • 陌南尘Y:楼主 楼主
      • 北漂少年郎:楼主可否提供下demo

      本文标题:iOS 集成环信(会话列表,聊天,昵称头像设置,自定义cell)

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