一、环信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的时候,可以根据扩展消息来判断
添加自定义的cell8.设置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)关于接受到通知,用户点击通知启动程序的回调看下面的截图
关于用户点击通知启动程序的回调方法解析如果文章中有什么错误或者更好的实现方式,欢迎各位留言指点,谢谢~
网友评论
/****
我指定头像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;
}
***/
跟您写的有哪里不一样吗?
cellForMessageModel:(id<IMessageModel>)messageModel 自定义这个方法不掉用如何解决
2.在messageViewController:(EaseMessageViewController *)viewController
modelForMessage:(EMMessage *)message里面 加个判断,如果从消息扩展里面取的头像跟自己本地不一致的时候,就需要先将新的头像缓存,并替换旧头像,并且需要刷新tableView 。 设头像的时候就用自己写好的根据 id 获取头像 如:[[HXUserInfoMang share] getImageUrlWithID:self._id] 来设置头像就行了
注意:messageViewController:(EaseMessageViewController *)viewController
modelForMessage这个方法,是有多少行就会调多少次,自己发一条消息就是有多少行调几次,别人发了一条消息过来就只会调一次,所以,你要在判断对方头像变化了的时候,刷新tableView ,不然还是会出现头像不一致
// 实时接收消息
-(void)conversationListDidUpdate:(NSArray *)aConversationList{
[self tableViewDidTriggerHeaderRefresh];
}