====== EaseUI 使用指南 ====== ---- ''EaseUI已不再维护,新用户建议集成新版UI库 'EaseIMKit' 文档地址:[[http://docs-im.easemob.com/im/ios/other/easeimkit|EaseIMKit集成]]'' ===== 简介 ===== EaseUI 封装了 IM 功能常用的控件(如聊天会话、会话列表、联系人列表)。旨在帮助开发者快速集成环信 SDK。 源码地址: * [[https://github.com/easemob/easeui_ios/tree/sdk3.x|EaseUI工程]] * [[https://github.com/easemob/sdkdemoapp3.0_ios/tree/sdk3.x|Demo3.0工程]] ===== 视频教程 ===== 以下是EaseUI集成参考视频,您可以通过视频学习如何集成环信SDK。 * [[https://ke.qq.com/webcourse/index.html#cid=320169&term_id=100380031&taid=2357924160922281&vid=z1428vxxdj0|OC_EaseUI集成]] * [[https://ke.qq.com/webcourse/index.html#cid=320169&term_id=100380031&taid=2357932750856873&vid=o1428qrmocv|Swift_EaseUI集成]] ===== 快速集成 ===== === 方法一: === pod 'EaseUI', :git => 'https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git' pod 'EaseUILite', :git =>'https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git' 如果要指定版本,可以在后面添加tag,如 pod 'EaseUI', :git => 'https://github.com/easemob/easeui-ios-hyphenate-cocoapods.git', :tag => ‘3.3.4’ 具体tag号和对应sdk版本号,可以从 https://github.com/easemob/easeui-ios-hyphenate-cocoapods/tags查看 **注意:** EaseUI:对应Hyphenate SDK(sdk包含实时音视频) EaseUILite:对应HyphenateLite SDK(sdk不包含实时音视频) Pod集成EaseUI时,会同时通过Pod集成SDK === 方法二:=== * 集成 EaseUI 前,首先需要集成环信 iOS SDK,参考:集成文档 * 参考ChatDemo3.0 导入的方式,直接将EaseUI拖入已经集成SDK的项目中 **注意:** * 添加的SDK要和EaseUI是同时下载的(目的是版本一致)。 * 如果使用Lite版本SDK,并用拖动的方式添加EaseUI, 需要在 ''Build Settings'' > ''GCC_PREPROCESSOR_DEFINITIONS'' 中添加 ''ENABLE_LITE=1'' (等号左右不能有空格) **easeui中包含了拍照,发语音,发图片,发位置的功能,使用了录音,摄像头,相册,地理位置的权限。需要在您项目的info.plist中添加对应权限。** ===== 初始化 ===== 第 1 步:引入相关头文件 #import "EaseUI.h"。 第 2 步:在工程的 AppDelegate 中的以下方法中,调用 EaseUI 对应方法。(注: 此方法不需要重复调用) [[EaseSDKHelper shareHelper] hyphenateApplication:application didFinishLaunchingWithOptions:launchOptions appkey:appkey apnsCertName:apnsCertName otherConfig:@{kSDKConfigEnableConsoleLogger:[NSNumber numberWithBool:YES]}]; ===== 聊天会话 ===== 创建聊天会话、传递用户或群 ID 和会话类型(EMConversationType)。 EaseMessageViewController *chatController = [[EaseMessageViewController alloc] initWithConversationChatter:@"8001" conversationType:EMConversationTypeChat]; ===== 聊天页面刷新 ===== EaseRefreshTableViewController提供了列表上拉加载、下拉刷新(加载)功能的UIViewController,其中已添加控件UITableView,默认未开启上拉加载、下来刷新(加载)的功能 ==== 实现上拉加载功能 ==== 继承自**EaseRefreshTableViewController**的子类,开启上拉加载需要设置showRefreshFooter为YES,并重写父类方法**- (void)tableViewDidTriggerFooterRefresh;**,如下: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.showRefreshFooter = YES; } - (void)tableViewDidTriggerFooterRefresh { //子类需要重写此方法 } ==== 实现下拉加载(刷新)功能 ==== 继承自**EaseRefreshTableViewController**的子类,开启下拉加载(刷新)需要设置showRefreshHeader为YES,并重写父类方法**- (void)tableViewDidTriggerHeaderRefresh;**,如下: - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.showRefreshHeader = YES; } - (void)tableViewDidTriggerHeaderRefresh { //子类需要重写此方法 } ===== 聊天会话功能扩展 ===== EaseUI 提供现成的聊天会话 ViewController,可以通过继承 EaseMessageViewController 方式(参考 ChatDemo-UI3.0 中 ChatViewController)实现对聊天会话的扩展。 也可以直接使用 EaseMessageViewController,通过 EaseMessageViewControllerDelegate 和 EaseMessageViewControllerDataSource 两个协议实现对 EaseMessageViewController 的扩展。 ==== 实现自定义聊天样式 ==== EaseMessageViewControllerDelegate 获取自定义消息 cell,根据 messageModel,用户自己判断是否显示自定义消息 cell。如果返回 nil 会显示默认;如果返回 cell 会显示用户自定义消息cell。 /*! @method @brief 获取消息自定义cell @discussion 用户根据messageModel判断是否显示自定义cell。返回nil显示默认cell,否则显示用户自定义cell @param tableView 当前消息视图的tableView @param messageModel 消息模型 @result 返回用户自定义cell */ - (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id)messageModel; /*! @method @brief 获取消息cell高度 @discussion 用户根据messageModel判断,是否自定义显示cell的高度 @param viewController 当前消息视图 @param messageModel 消息模型 @param cellWidth 视图宽度 @result 返回用户自定义cell */ - (CGFloat)messageViewController:(EaseMessageViewController *)viewController heightForMessageModel:(id)messageModel withCellWidth:(CGFloat)cellWidth; //具体创建自定义Cell的样例: - (UITableViewCell *)messageViewController:(UITableView *)tableView cellForMessageModel:(id)model { //样例为如果消息是文本消息显示用户自定义cell if (model.bodyType == eMessageBodyType_Text) { NSString *CellIdentifier = [CustomMessageCell cellIdentifierWithModel:model]; //CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell CustomMessageCell *cell = (CustomMessageCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[CustomMessageCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier model:model]; cell.selectionStyle = UITableViewCellSelectionStyleNone; } cell.model = model; return cell; } return nil; } - (CGFloat)messageViewController:(EaseMessageViewController *)viewController heightForMessageModel:(id)messageModel withCellWidth:(CGFloat)cellWidth { //样例为如果消息是文本消息使用用户自定义cell的高度 if (messageModel.bodyType == EMMessageBodyTypeText) { //CustomMessageCell为用户自定义cell,继承了EaseBaseMessageCell return [CustomMessageCell cellHeightWithModel:messageModel]; } return 0.f; } 通过自定义cell展示动态表情的效果图: {{:start:300iosclientintegration:ios_easeui_chatview_customcell.png?200|通过自定义cell展示动态表情的效果图}} 选中消息的回调 /*! @method @brief 选中消息的回调 @discussion 用户根据messageModel判断,是否自定义处理消息选中时间。返回YES为自定义处理,返回NO为默认处理 @param viewController 当前消息视图 @param messageModel 消息模型 @result 是否采用自定义处理 */ - (BOOL)messageViewController:(EaseMessageViewController *)viewController didSelectMessageModel:(id)messageModel; //选中消息回调的样例: - (BOOL)messageViewController:(EaseMessageViewController *)viewController didSelectMessageModel:(id)messageModel { BOOL flag = NO; //样例为如果消息是文件消息用户自定义处理选中逻辑 switch (messageModel.bodyType) { case EMMessageBodyTypeImage: case EMMessageBodyTypeLocation: case EMMessageBodyTypeVideo: case EMMessageBodyTypeVoice: break; case EMMessageBodyTypeFile: { flag = YES; NSLog(@"用户自定义实现"); } break; default: break; } return flag; } 用户选中头像的回调 /*! @method @brief 点击消息头像 @discussion 获取用户点击头像回调 @param viewController 当前消息视图 @param messageModel 消息模型 @result */ - (void)messageViewController:(EaseMessageViewController *)viewController didSelectAvatarMessageModel:(id)messageModel; //获取用户点击头像回调的样例: - (void)messageViewController:(EaseMessageViewController *)viewController didSelectAvatarMessageModel:(id)messageModel { //UserProfileViewController用户自定义的个人信息视图 //样例的逻辑是选中消息头像后,进入该消息发送者的个人信息 UserProfileViewController *userprofile = [[UserProfileViewController alloc] initWithUsername:messageModel.message.from]; [self.navigationController pushViewController:userprofile animated:YES]; } 录音按钮状态的回调 /*! @method @brief 底部录音功能按钮状态回调 @discussion 获取底部录音功能按钮状态回调,根据EaseRecordViewType,用户自定义处理UI的逻辑 @param viewController 当前消息视图 @param recordView 录音视图 @param type 录音按钮当前状态 @result */ - (void)messageViewController:(EaseMessageViewController *)viewController didSelectRecordView:(UIView *)recordView withEvenType:(EaseRecordViewType)type; //录音按钮状态的回调样例: - (void)messageViewController:(EaseMessageViewController *)viewController didSelectRecordView:(UIView *)recordView withEvenType:(EaseRecordViewType)type { /* EaseRecordViewTypeTouchDown,//录音按钮按下 EaseRecordViewTypeTouchUpInside,//手指在录音按钮内部时离开 EaseRecordViewTypeTouchUpOutside,//手指在录音按钮外部时离开 EaseRecordViewTypeDragInside,//手指移动到录音按钮内部 EaseRecordViewTypeDragOutside,//手指移动到录音按钮外部 */ //根据type类型,用户自定义处理UI的逻辑 switch (type) { case EaseRecordViewTypeTouchDown: { if ([self.recordView isKindOfClass:[EaseRecordView class]]) { [(EaseRecordView *)self.recordView recordButtonTouchDown]; } } break; case EaseRecordViewTypeTouchUpInside: { if ([self.recordView isKindOfClass:[EaseRecordView class]]) { [(EaseRecordView *)self.recordView recordButtonTouchUpInside]; } [self.recordView removeFromSuperview]; } break; case EaseRecordViewTypeTouchUpOutside: { if ([self.recordView isKindOfClass:[EaseRecordView class]]) { [(EaseRecordView *)self.recordView recordButtonTouchUpOutside]; } [self.recordView removeFromSuperview]; } break; case EaseRecordViewTypeDragInside: { if ([self.recordView isKindOfClass:[EaseRecordView class]]) { [(EaseRecordView *)self.recordView recordButtonDragInside]; } } break; case EaseRecordViewTypeDragOutside: { if ([self.recordView isKindOfClass:[EaseRecordView class]]) { [(EaseRecordView *)self.recordView recordButtonDragOutside]; } } break; default: break; } } EaseMessageViewControllerDataSource 用户判断消息是否允许长按,返回布尔值;如果用户允许长按,此方法为通知用户触发长按手势,返回布尔值,如果返回 NO 默认方式处理,返回 YES 采用用户自定义的处理方式。 /*! @method @brief 是否允许长按 @discussion 获取是否允许长按的回调,默认是NO @param viewController 当前消息视图 @param indexPath 长按消息对应的indexPath @result */ - (BOOL)messageViewController:(EaseMessageViewController *)viewController canLongPressRowAtIndexPath:(NSIndexPath *)indexPath; /*! @method @brief 触发长按手势 @discussion 获取触发长按手势的回调,默认是NO @param viewController 当前消息视图 @param indexPath 长按消息对应的indexPath @result */ - (BOOL)messageViewController:(EaseMessageViewController *)viewController didLongPressRowAtIndexPath:(NSIndexPath *)indexPath; //长按收拾回调样例: - (BOOL)messageViewController:(EaseMessageViewController *)viewController canLongPressRowAtIndexPath:(NSIndexPath *)indexPath { //样例给出的逻辑是所有cell都允许长按 return YES; } - (BOOL)messageViewController:(EaseMessageViewController *)viewController didLongPressRowAtIndexPath:(NSIndexPath *)indexPath { //样例给出的逻辑是长按cell之后显示menu视图 id object = [self.dataArray objectAtIndex:indexPath.row]; if (![object isKindOfClass:[NSString class]]) { EaseMessageCell *cell = (EaseMessageCell *)[self.tableView cellForRowAtIndexPath:indexPath]; [cell becomeFirstResponder]; self.menuIndexPath = indexPath; [self _showMenuViewController:cell.bubbleView andIndexPath:indexPath messageType:cell.model.bodyType]; } return YES; } Demo3.0实现的消息长按效果演示: {{:start:300iosclientintegration:ios_easeui_chatview_menu.png?200|Demo3.0实现的消息长按效果演示}} 将EMMessage类型转换为符合协议的类型,设置用户信息,消息显示用户昵称和头像。 /*! @method @brief 将EMMessage类型转换为符合协议的类型 @discussion 将EMMessage类型转换为符合协议的类型,设置用户信息,消息显示用户昵称和头像 @param viewController 当前消息视图 @param EMMessage 聊天消息对象类型 @result 返回协议的类型 */ - (id)messageViewController:(EaseMessageViewController *)viewController modelForMessage:(EMMessage *)message; //具体样例: - (id)messageViewController:(EaseMessageViewController *)viewController modelForMessage:(EMMessage *)message { //用户可以根据自己的用户体系,根据message设置用户昵称和头像 id model = nil; model = [[EaseMessageModel alloc] initWithMessage:message]; model.avatarImage = [UIImage imageNamed:@"EaseUIResource.bundle/user"];//默认头像 model.avatarURLPath = @"";//头像网络地址 model.nickname = @"昵称";//用户昵称 return model; } 聊天会话页面头像和昵称的效果演示: {{:start:300iosclientintegration:ios_easeui_chatview.png?200|聊天会话页面头像和昵称的效果演示}} ==== 聊天会话样式自定义 ==== 聊天样式的自定义需要在 EaseMessageViewController 中 viewDidload 结束前设置。\\ @property中带有UI_APPEARANCE_SELECTOR,都可以通过set的形式设置样式,具体可以参考EaseBaseMessageCell.h,EaseMessageCell.h\\ === 发送气泡图片设置 === [[EaseBaseMessageCell appearance] setSendBubbleBackgroundImage:[[UIImage imageNamed:@"chat_sender_bg"] stretchableImageWithLeftCapWidth:5 topCapHeight:35]];//设置发送气泡 [[EaseBaseMessageCell appearance] setRecvBubbleBackgroundImage:[[UIImage imageNamed:@"chat_receiver_bg"] stretchableImageWithLeftCapWidth:35 topCapHeight:35]];//设置接收气泡 === 头像设置 === [[EaseBaseMessageCell appearance] setAvatarSize:40.f];//设置头像大小 [[EaseBaseMessageCell appearance] setAvatarCornerRadius:20.f];//设置头像圆角 === 消息字体颜色设置 === [[EaseMessageCell appearance] setMessageTextFont:[UIFont systemFontOfSize:15]];//消息显示字体 [[EaseMessageCell appearance] setMessageTextColor:[UIColor blackColor]];//消息显示颜色 [[EaseMessageCell appearance] setMessageLocationFont:[UIFont systemFontOfSize:12]];//位置消息显示字体 [[EaseMessageCell appearance] setMessageLocationColor:[UIColor whiteColor]];//位置消息显示颜色 === 语音消息图片样式设置 === [[EaseBaseMessageCell appearance] setSendMessageVoiceAnimationImages:@[[UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_full"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_000"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_001"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_002"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_sender_audio_playing_003"]]];//发送者语音消息播放图片 [[EaseBaseMessageCell appearance] setRecvMessageVoiceAnimationImages:@[[UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing_full"],[UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing000"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing001"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing002"], [UIImage imageNamed:@"EaseUIResource.bundle/chat_receiver_audio_playing003"]]];//接收者语音消息播放图片 ==== 聊天会话输入框自定义 ==== 继承EaseMessageViewController,或者EaseMessageViewController的实例调用以下方法设置底部输入框 CustomerInputView *inputView = [[CustomerInputView alloc] init];//CustomerInputView用户自定义底部输入框 [self setChatToolbar:inputView]; 实现默认底部输入框delegate @interface CustomerInputView : UIView @property (weak, nonatomic) id delegate; @end === 自定义输入框发送消息 === - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{ if ([text isEqualToString:@"\n"]){ if(self.delegate && [self.delegate respondsToSelector:@selector(didSendText:)]) { [self.delegate didSendText:self.textView.text]; } self.textView.text = @""; self.placeholderLabel.text = @"说点什么吧..."; return NO; } return YES; } === 自定义输入框高度变化 === //这是一个举例,初始化输入框的时候注册监听键盘高度变化 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:)name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:)name:UIKeyboardWillHideNotification object:nil]; - (void)keyboardWillShow:(NSNotification *)aNotification{ //获取键盘的高度 NSValue *aValue = [[aNotification userInfo] objectForKey:UIKeyboardFrameEndUserInfoKey]; CGRect keyboardRect = [aValue CGRectValue]; if (keyboardRect.size.height > self.keyboardHeight) { self.keyboardHeight = keyboardRect.size.height; } self.frame = CGRectMake(0, _originY - self.keyboardHeight - 64, App_Width, self.inputH + self.keyboardHeight); if (self.delegate && [self.delegate respondsToSelector:@selector(chatToolbarDidChangeFrameToHeight:)]) { [self.delegate chatToolbarDidChangeFrameToHeight:self.frame.size.height]; } } - (void)keyboardWillHide:(NSNotification *)aNotification{ self.frame = CGRectMake(0, _originY - 64, App_Width, self.inputH) ; if (self.delegate && [self.delegate respondsToSelector:@selector(chatToolbarDidChangeFrameToHeight:)]) { [self.delegate chatToolbarDidChangeFrameToHeight:self.frame.size.height]; } } ==== 聊天会话底部菜单自定义 ==== **EaseChatBarMoreView**为自定义的功能菜单选择视图,目前已添加的功能有:\\ /*! @method @brief 新增一个新的功能按钮 @discussion @param image 按钮图片 @param highLightedImage 高亮图片 @param title 按钮标题 @result */ - (void)insertItemWithImage:(UIImage*)image highlightedImage:(UIImage*)highLightedImage title:(NSString*)title; /*! @method @brief 修改功能按钮图片 @discussion @param image 按钮图片 @param highLightedImage 高亮图片 @param title 按钮标题 @param index 按钮索引 @result */ - (void)updateItemWithImage:(UIImage*)image highlightedImage:(UIImage*)highLightedImage title:(NSString*)title atIndex:(NSInteger)index; /*! @method @brief 根据索引删除功能按钮 @discussion @param index 按钮索引 @result */ - (void)removeItematIndex:(NSInteger)index; 各个选项的功能需要ViewController实现EaseChatBarMoreViewDelegate协议中的回调方法来编写或调整. ===== 消息发送 ===== EaseSDKHelper 封装了发送消息的方法。 具体发送消息样例: /* EMChatTypeChat 单聊消息 EMChatTypeGroupChat 群聊消息 EMChatTypeChatRoom 聊天室消息 */ //发送文字消息 EMMessage *message = [EaseSDKHelper sendTextMessage:@"要发送的消息" to:@"6001"//接收方 messageType:EMChatTypeChat//消息类型 messageExt:nil]; //扩展信息 //发送位置消息 EMMessage *message = [EaseSDKHelper sendLocationMessageWithLatitude:35.1//经度 longitude:35.1//纬度 address:"地址" to:@"6001"//接收方 messageType:EMChatTypeChat//消息类型 messageExt:nil];//扩展信息 //发送图片消息 EMMessage *message = [EaseSDKHelper sendImageMessageWithImageData:imageData//发送的图片数据NSData to:@"6001"//接收方 messageType:EMChatTypeChat//消息类型 messageExt:nil];//扩展信息 //发送音频消息 EMMessage *message = [EaseSDKHelper sendVoiceMessageWithLocalPath:localPath//音频本地地址 duration:duration//语音的时长,单位是秒 to:@"6001"//接收方 messageType:EMChatTypeChat//消息类型 messageExt:nil];//扩展信息 //发送视频文件消息 EMMessage *message = [EaseSDKHelper sendVideoMessageWithURL:url//发送的视频地址 to:@"6001"//接收方 messageType:EMChatTypeChat//消息类型 messageExt:nil];//扩展信息 //发送构造成功的消息 [[EMClient sharedClient].chatManager asyncSendMessage:message progress:nil completion:^(EMMessage *aMessage, EMError *aError) { }]; ===== 会话列表 ===== ==== 会话列表初始化 ==== EaseConversationListViewController *chatListVC = [[EaseConversationListViewController alloc] init]; ==== 会话列表下拉刷新 ==== 需要继承**EaseConversationListViewController**的子类,在viewDidLoad中加入 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.showRefreshHeader = YES; //首次进入加载数据 [self tableViewDidTriggerHeaderRefresh]; } ==== 会话列表扩展 ==== EaseConversationListViewControllerDataSource 用户根据 conversationModel 实现,实现自定义会话中最后一条消息文案的显示内容。 /*! @method @brief 获取最后一条消息显示的内容 @discussion 用户根据conversationModel实现,实现自定义会话中最后一条消息文案的显示内容 @param conversationListViewController 当前会话列表视图 @param IConversationModel 会话模型 @result 返回用户最后一条消息显示的内容 */ - (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController latestMessageTitleForConversationModel:(id)conversationModel; /*! @method @brief 获取最后一条消息显示的时间 @discussion 用户可以根据conversationModel,自定义实现会话列表中时间文案的显示内容 @param conversationListViewController 当前会话列表视图 @param IConversationModel 会话模型 @result 返回用户最后一条消息时间的显示文案 */ - (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController latestMessageTimeForConversationModel:(id)conversationModel; //最后一条消息展示内容样例 - (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController latestMessageTitleForConversationModel:(id)conversationModel { NSString *latestMessageTitle = @""; EMMessage *lastMessage = [conversationModel.conversation latestMessage]; if (lastMessage) { EMMessageBody *messageBody = lastMessage.body; switch (messageBody.type) { case EMMessageBodyTypeImage:{ latestMessageTitle = NSLocalizedString(@"message.image1", @"[image]"); } break; case EMMessageBodyTypeText:{ // 表情映射。 NSString *didReceiveText = [EaseConvertToCommonEmoticonsHelper convertToSystemEmoticons:((EMTextMessageBody *)messageBody).text]; latestMessageTitle = didReceiveText; if ([lastMessage.ext objectForKey:MESSAGE_ATTR_IS_BIG_EXPRESSION]) { latestMessageTitle = @"[动画表情]"; } } break; case EMMessageBodyTypeVoice:{ latestMessageTitle = NSLocalizedString(@"message.voice1", @"[voice]"); } break; case EMMessageBodyTypeLocation: { latestMessageTitle = NSLocalizedString(@"message.location1", @"[location]"); } break; case EMMessageBodyTypeVideo: { latestMessageTitle = NSLocalizedString(@"message.video1", @"[video]"); } break; case EMMessageBodyTypeFile: { latestMessageTitle = NSLocalizedString(@"message.file1", @"[file]"); } break; default: { } break; } } return latestMessageTitle; } //最后一条消息展示时间样例 - (NSString *)conversationListViewController:(EaseConversationListViewController *)conversationListViewController latestMessageTimeForConversationModel:(id)conversationModel { NSString *latestMessageTime = @""; EMMessage *lastMessage = [conversationModel.conversation latestMessage];; if (lastMessage) { latestMessageTime = [NSDate formattedTimeFromTimeInterval:lastMessage.timestamp]; } return latestMessageTime; } 会话列表最后一条消息和时间显示的效果演示: {{:start:300iosclientintegration:ios_easeui_conversation.png?200|会话列表最后一条消息和时间显示的效果演示}} EaseConversationListViewControllerDelegate 点击会话列表用户可以根据 conversationModel 自定义处理逻辑。 /*! @method @brief 获取点击会话列表的回调 @discussion 获取点击会话列表的回调后,点击会话列表用户可以根据conversationModel自定义处理逻辑 @param conversationListViewController 当前会话列表视图 @param IConversationModel 会话模型 @result */ - (void)conversationListViewController:(EaseConversationListViewController *)conversationListViewController didSelectConversationModel:(id)conversationModel; //会话列表点击的回调样例 - (void)conversationListViewController:(EaseConversationListViewController *)conversationListViewController didSelectConversationModel:(id)conversationModel { //样例展示为根据conversationModel,进入不同的会话ViewController if (conversationModel) { EMConversation *conversation = conversationModel.conversation; if (conversation) { if ([[RobotManager sharedInstance] isRobotWithUsername:conversation.conversationId]) { RobotChatViewController *chatController = [[RobotChatViewController alloc] initWithConversationChatter:conversation.conversationId conversationType:conversation.type]; chatController.title = [[RobotManager sharedInstance] getRobotNickWithUsername:conversation.conversationId]; [self.navigationController pushViewController:chatController animated:YES]; } else { ChatViewController *chatController = [[ChatViewController alloc] initWithConversationChatter:conversation.conversationId conversationType:conversation.type]; chatController.title = conversationModel.title; [self.navigationController pushViewController:chatController animated:YES]; } } [[NSNotificationCenter defaultCenter] postNotificationName:@"setupUnreadMessageCount" object:nil]; [self.tableView reloadData]; } } ===== 联系人列表 ===== ==== 联系人列表初始化 ==== EaseUsersListViewController *listViewController = [[EaseUsersListViewController alloc] init]; ==== 联系人列表下拉刷新 ==== 需要继承**EaseUsersListViewController**的子类,在viewDidLoad中加入 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. self.showRefreshHeader = YES; } ==== 联系人列表扩展 ==== 需要实现 EMUserListViewControllerDataSource。 根据 buddy 获取用户自定信息,联系人列表里展示昵称和头像。 /*! @method @brief 获取用户模型 @discussion 根据buddy获取用户自定信息,联系人列表里展示昵称和头像 @param userListViewController 当前联系人视图 @param buddy 好友的信息描述类 @result 返回用户模型 */ - (id)userListViewController:(EaseUsersListViewController *)userListViewController modelForBuddy:(NSString *)buddy; //联系人列表扩展样例 - (id)userListViewController:(EaseUsersListViewController *)userListViewController modelForBuddy:(NSString *)buddy { //用户可以根据自己的用户体系,根据buddy设置用户昵称和头像 id model = nil; model = [[EaseUserModel alloc] initWithBuddy:buddy]; model.avatarURLPath = @"";//头像网络地址 model.nickname = @"昵称";//用户昵称 return model; } 联系人列表头像和昵称的效果演示: {{:start:300iosclientintegration:ios_easeui_contact.png?200|联系人列表头像和昵称的效果演示}} ===== EaseUI中使用的第三方库 ===== * MBProgressHUD * MJRefresh * MWPhotoBrowser * SDWebImage * DACircularProgressView ==== EaseUI中第三方库冲突问题 ==== 目前推荐Pod的方式集成EaseUI。如果集成了EaseUI,而且上述第三方依赖在开发者的代码中也有引用,会造成冲突,无法编译,针对此问题有如下两种场景: * 开发者使用的第三方依赖也是通过pod方式集成,这样pod只会安装一份,不会重复安装多个版本。如果是依赖版本不兼容,例如开发者依赖了'''MBProgressHUD', '~> 1.0.0' '',而EaseUI通过MWPhotoBrowser间接依赖了'''MBProgressHUD', '~> 0.9' '',这样会导致pod install失败,开发者可以改变''MBProgressHUD''的依赖版本。EaseUI也会在后续版本中尽量减少使用第三方依赖。 * 如果是手动导入了上述第三方库,建议直接删除手动导入的部分,避免冲突的产生,如果EaseUI使用第三方库的版本不能满足开发者的需求,开发者也可以手动将第三方库进行重命名,保证兼容(手动方式集成EaseUI也可以参考此解决方案)。 ---- 上一页:[[im:ios:apns:content|APNs 内容解析]] 下一页:[[im:ios:other:privatecloud|私有云SDK集成配置]]