因为项目以前的环信,是要用到环信的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#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的初始化,登录,注册什么的 就不说了,自己看文档去吧。
这里主要说下基于EaseUI,实现消息列表页和聊天界面
环信默认的聊天界面
因为环信提供的聊天界面和消息列表界面,是没有昵称和头像的,一般的用户的图片和用户名,都是存在自己服务器的,那怎么把聊天界面中的头像和用户名换成自己的服务器上的数据?
方法一:从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)conversationListViewController:(EaseConversationListViewController *)conversationListViewController modelForConversation:(EMConversation *)conversation
此代理是在EaseConversationListViewControllerDataSource协议中的,所以ChatListViewController(继承EaseConversationListViewController的类)要遵从协议,并且self.dataSource = self;
此方法是返回一个遵从IConversationModel代理的model,这个model就是cell的数据源,EaseUI已经帮我们写好了一个model,我们直接创建,然后赋值就好了
- (id)conversationListViewController:(EaseConversationListViewController *)conversationListViewController modelForConversation:(EMConversation *)conversation{ //用环信提供的model就可以了 EaseConversationModel *model = [[EaseConversationModel alloc] initWithConversation:conversation]; //然后根据用户名 往上面赋值 //self.imageAndNameArray为自定义的数组,其中存储的是从自己服务器上请求下来的数据 //数据包括,昵称,头像和默认图片for(HPChatListDataModel *dataModelinself.imageAndNameArray) {if([dataModel.mobile isEqualToString:model.conversation.conversationId]) {//根据用户名对应起来 model.avatarURLPath = dataModel.pic;//头像的网络图片 model.avatarImage = [dataModel getDefaultImage];//头像的默认图片 model.title = dataModel.name;//昵称 } }returnmodel;}
主要是在那个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)conversationModel{ NSString *latestMessageTime = @""; EMMessage *lastMessage = [conversationModel.conversation latestMessage];;if(lastMessage) { //这个方法是环信提供的 latestMessageTime = [NSDate formattedTimeFromTimeInterval:lastMessage.timestamp]; }returnlatestMessageTime;}
其中方法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)conversationModel;
实现:
- (void)conversationListViewController:(EaseConversationListViewController *)conversationListViewController
didSelectConversationModel:(id)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)messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message
实现:
- (id)messageViewController:(EaseMessageViewController *)viewController modelForMessage:(EMMessage *)message{//用户可以根据自己的用户体系,根据message设置用户昵称和头像id 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;//用户昵称returnmodel;}
2、去掉多余的功能按钮
//删除电话和视频//这里为什么要移除3两次,因为执行第一次后,后一个的索引变成了3[self.chatBarMoreView removeItematIndex:3]; [self.chatBarMoreView removeItematIndex:3];
好了 完成
对了,我这里的聊天界面,只是支持单聊,以后项目如果支持群组的话 ,那再来更新