环信iOS学习笔记阅读理解

环信SDK3.2.3和EaseUI消息列表和聊天的简单实现

2017-01-19  本文已影响2753人  简单日记

这几天趁着比较闲,就整理了下项目中的环信。貌似还是2.x,看着不爽,果断要升级啊。

但是以前没集成过环信,第一次集成遇到了好多坑,特写下记下

好,开始了。

因为项目以前的环信,是要用到环信的EaseUI的。所以集成的时候,只能手动导入(原因下面会说到),这里介绍的也是手动导入。

从环信官网上下来的包如图

环信开发包
然后目录解释环信文档上也有解释

从官网上下载下来的包中分为如下五部分:

环信 iOS HyphenateSDK 开发使用(不包含实时通话功能)

环信 iOS HyphenateFullSDK 开发使用(包含实时通话功能)

环信 iOS doc SDK 相关API文档

环信 iOS ChatUIDemo3.0 工程源码

环信 iOS EaseUI 工程源码

环信 iOS chatdemo-ui-3.x.x.ipa 打包的 spa

上面提过,项目中要用EaseUI,所以别看环信给了你两个选择,可以导入一个不包含实时通话的,可以小一点。但是环信封装的EaseUI里面,引用的库是包含实时通话的HyphenateFullSDK,所以 ,只能导入HyphenateFullSDK库。。。蛋疼。

这时候有小伙伴就说,那我可以cocopod导入HyphenateFullSDK库,然后手动导入EaseUI啊。


本人试过,结果就是,EaseUI内部会报错方法找不到,然后你对比一下cocopod导入的HyphenateFullSDK库比手动导入的HyphenateFullSDK库会少几个方法。。。少的就是那几个报错的方法。。。

本人pod search了一下 看了一下版本 Hyphenate 的版本是3.1.5,但是下载下来的是3.2.3。。。我有点方了。。。

然后想了一种方法,手动导入Hyphenate 但是pod EaseUI。但是有朋友说,EaseUI最好手动导入,因为有可能你会修改EaseUI,所以不建议pod。环信默认的聊天界面环信默认的聊天界面


好吧,我认命了,按环信文档手动导入Hyphenate和EaseUI,并添加系统依赖库。

然后,编译失败。。。

你可以看一下错误,基本就是找不到UIKit,

解决方法:在pch文件中加入UIKit,注意,OBJC千万不要忘。

#ifdef __OBJC__
#import<UIKit/UIKit.h>
#endif

然后再编译,又失败。。。

看了一下,跟项目中本身的MJ库冲突,没办法,只能删了。

然后再编译,又错。。。这次是我的错,环信不支持Bitcode,记得Bitcode为NO

然后在编译,过了,恩,Nice。

运行,然后崩了。。。

卧槽,我只是导入啊,代码还没开始写那。难道是我打开的方式不对?

试了几次,发现连Appdelegate都没进去。。。

崩溃的地方和打印
然后上网找了一圈,看到了一位大哥说的,说出现Reason: image not found错误,把Hyphenate.Framework库要改成Optional就好了,如图下。


示例图
改完以后,果然好了,当时心里各种感觉大哥啊。然后就开始写代码,但是出现一个问题,登录的block一直不回调,但是也没有错误。环信也没有日志。。。我感觉我貌似被坑了。。。

对照了一下环信的示例demo,人家的Hyphenate.Framework也不是Optional啊。但是在Build Phases里多了一行

环信demo的Build Phases
尼玛,坑爹啊,多的这个为毛文档里没有。

加上了这个,果然好了。

那位大哥,我很好奇,你是怎么用那个方法解决的。。。

对于SDK的初始化,登录,注册什么的 就不说了,自己看文档去吧。

2017.7.13更新
不知道是不是环信更新了还是怎么了,这次的项目中用pod管理环信,一点问题也没有,棒棒的顺利啊
podfile中
pod 'Hyphenate' #环信聊天Full版本
pod 'EaseUI', :git => 'https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git' #环信自定义UI

然后直接pod install就好了
注意:先确定你项目中有没有MJRefresh 如果有 请注释掉,要不install的时候,pod会提示你冲突,install失败

这里主要说下基于EaseUI,实现消息列表页和聊天界面

C91EECE0-F857-42C2-B1BA-EE72DED6735E.png

环信默认的聊天界面
因为环信提供的聊天界面和消息列表界面,是没有昵称和头像的,一般的用户的图片和用户名,都是存在自己服务器的,那怎么把聊天界面中的头像和用户名换成自己的服务器上的数据?

方法一:从APP服务器获取昵称和头像昵称和头像的获取:当收到一条消息(群消息)时,得到发送者的用户ID,然后查找手机本地数据库是否有此用户ID的昵称和头像,如没有则调用APP服务器接口通过用户ID查询出昵称和头像,然后保存到本地数据库和缓存,下次此用户发来信息即可直接查询缓存或者本地数据库,不需要再次向APP服务器发起请求。

昵称和头像的更新:当点击发送者头像时加载用户详情时从APP服务器查询此用户的具体信息然后更新本地数据库和缓存。当用户自己更新昵称或头像时,也可以发送一条透传消息到其他用户和用户所在的群,来更新该用户的昵称和头像。

方法二:从消息扩展中获取昵称和头像

昵称和头像的获取:把用户基本的昵称和头像的URL放到消息的扩展中,通过消息传递给接收方,当收到一条消息时,则能通过消息的扩展得到发送者的昵称和头像URL,然后保存到本地数据库和缓存。当显示昵称和头像时,请从本地或者缓存中读取,不要直接从消息中把赋值拿给界面(否则当用户昵称改变后,同一个人会显示不同的昵称)。

昵称和头像的更新:当扩展消息中的昵称和头像 URI 与当前本地数据库和缓存中的相应数据不同的时候,需要把新的昵称保存到本地数据库和缓存,并下载新的头像并保存到本地数据库和缓存。
上面是两种环信文档中介绍的,我采用的算是第一种(其实我感觉那种都不算。。。),就是把服务器上的昵称和头像填到聊天界面和消息列表界面中,表示本地数据库什么的,一点都不知道,环信你提供了么?在demo中倒是看到了,但是那个又不在EaseUI中,而且还涉及到另一个.framework,就没有导入。如果小伙伴有更好的方法,也可以简信告诉我。

所以大体的思路就是,服务器请求到的数据,填到消息列表和聊天界面上。

在EaseUI中,负责消息列表的是EaseConversationListViewController这个类

负责聊天界面的是EaseMessageViewController这个类

我的做法是分别用两个类继承他们两个,ChatViewController继承EaseMessageViewController,ChatListViewController继承EaseConversationListViewController。
然后在我继承的这个两个类中实现环信提供的代理方法,尽量不去改环信的EaseUI代码(里面那代码改起来也的疯啊,而且那么多,以后自己改的那些你还记得么?,还不如整一个新类)。

先说消息列表,有这几需求

需求:

1、昵称和头像

2、消息的时间,因为EaseUI默认的是日期,而不是几点几分

3、下拉刷新和空视图

4、点击推出的聊天详情

解决方案:

1、昵称和头像

EaseUI已经给我们提供了代理方法,只要实现代理方法,就可以自定义cell的样式了。方法名:

- (id<IConversationModel>)conversationListViewController:(EaseConversationListViewController *)conversationListViewController modelForConversation:(EMConversation *)conversation

此代理是在EaseConversationListViewControllerDataSource协议中的,所以ChatListViewController(继承EaseConversationListViewController的类)要遵从协议,并且self.dataSource = self;
此方法是返回一个遵从IConversationModel代理的model,这个model就是cell的数据源,EaseUI已经帮我们写好了一个model,我们直接创建,然后赋值就好了

- (id<IConversationModel>)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
                                    modelForConversation:(EMConversation *)conversation{
    //用环信提供的model就可以了
    EaseConversationModel *model = [[EaseConversationModel alloc] initWithConversation:conversation];
    //然后根据用户名  往上面赋值
    //self.imageAndNameArray为自定义的数组,其中存储的是从自己服务器上请求下来的数据
    //数据包括,昵称,头像和默认图片
    for (HPChatListDataModel *dataModel in self.imageAndNameArray) {
        if ([dataModel.mobile isEqualToString:model.conversation.conversationId]) {//根据用户名对应起来
            model.avatarURLPath = dataModel.pic;//头像的网络图片
            model.avatarImage = [dataModel getDefaultImage];//头像的默认图片
            model.title = dataModel.name;//昵称
        }
    }
    return model;
}

主要是在那个for循环中,给model赋值,就好了
但是这里有个问题,如果你们服务器返回的头像是圆的,那么会看起来头像四角是灰色的,这是因为环信的消息列表中,头像的imageView的背景颜色,设置成灰色的,所以,只能在EaseConversationListViewController类的

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

方法中加上,

cell.avatarView.imageView.backgroundColor = [UIColor whiteColor];

2、消息的时间

环信提供的方法:

- (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController

方法的实现:

//时间
- (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
       latestMessageTimeForConversationModel:(id<IConversationModel>)conversationModel{
    NSString *latestMessageTime = @"";
    EMMessage *lastMessage = [conversationModel.conversation latestMessage];;
    if (lastMessage) {
        //这个方法是环信提供的
        latestMessageTime = [NSDate formattedTimeFromTimeInterval:lastMessage.timestamp];
    }
    return latestMessageTime;
}

其中方法formattedTimeFromTimeInterva是环信EaseUI中提供的,要包含头文件

#import "NSDate+Category.h"//环信时间分类

3、下拉刷新和空视图

//打开下来刷新
    self.showRefreshHeader = YES;

实现下拉刷新的方法,

//下拉刷新  实现以下
- (void)tableViewDidTriggerHeaderRefresh{
//super必须要有  要不会有问题
    [super tableViewDidTriggerHeaderRefresh];
    //这里写下拉的方法
}

空视图

判断是否为空视图的话,直接判断self.dataArray.count就好了,父类的数据源数组就是这个。

4、点击推出的聊天详情

因为聊天详情要用我们自定义的ChatViewController(继承于EaseMessageViewController),所以点击推出的应该是我们自定义的,所以要实现代理方法:

- (void)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
            didSelectConversationModel:(id<IConversationModel>)conversationModel;

实现:

- (void)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
            didSelectConversationModel:(id<IConversationModel>)conversationModel{
    EaseConversationModel *model = (EaseConversationModel *)conversationModel;
    //自定义点击cell推出的viewcontroller
    ChatViewController *viewController = [HPChatViewController chatViewControllerWithConversationChatter:model.conversation.conversationId title:model.title imageUrl:model.avatarURLPath defaultImage:model.avatarImage];
    [self.navigationController pushViewController:viewController animated:YES];
}

聊天界面

需求:

1、替换昵称和头像

2、去掉多余的功能按钮

环信EaseUI提供的方法

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

实现:

- (id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
                           modelForMessage:(EMMessage *)message
{
    //用户可以根据自己的用户体系,根据message设置用户昵称和头像
    id<IMessageModel> model = nil;
//EaseMessageModel是环信EaseUI提供的model  直接引用就好了
    model = [[EaseMessageModel alloc] initWithMessage:message];
    //分两种情况  一种是当为当前用户的时候
    if ([model.nickname isEqualToString:[EMClient sharedClient].currentUsername]) {
        //默认图
        model.avatarImage = [UIImage imageNamed:@"DefaultImg"]
        //网络图
        model.avatarURLPath = accInfo.pic;
    }else{//当为对方的时候
        model.avatarURLPath = _imageUrl;//网络图
        model.avatarImage =  [UIImage imageNamed:@"DefaultImg"];
    }
    model.nickname = nil;//用户昵称
    return model;
}

2、去掉多余的功能按钮

    //删除电话和视频
   //这里为什么要移除3两次,因为执行第一次后,后一个的索引变成了3
    [self.chatBarMoreView removeItematIndex:3];
    [self.chatBarMoreView removeItematIndex:3];

好了 完成

对了,我这里的聊天界面,只是支持单聊,以后项目如果支持群组的话 ,那再来更新

上一篇下一篇

猜你喜欢

热点阅读