足球盘口软件
当前位置: 足球盘口软件 > 前端 >
iOS开发之环信,单表格写入

iOS开垦使用系统推送Notifaction和轮询达成轻巧谈天系统

话十分的少说,先看一下搞好的闲扯软件界面:

**图片 1



**

率先在StoryBoard里拖了叁个UItableView和三个view用来输入文字恐怕语音,右侧的开关用来切换文字和语音:

图片 2
闲扯里有两种id: orderID :闲谈id messageID :每条音信的ID sessionID :各个订单的会话ID,假使为空通过orderID央浼。
然后在viewDidLoad里做一些界面上的操作和一些开头化的操作:
1.设置一下tableview的headView
**图片 3


** 2.开端化录音、客商头像、获取订单实际情况

    //初始换录音
    [self initRecord];
    //获取用户头像
    [self getHeadImg];
    //获取订单详情
    [self getOrderDetailInfo];

3.在viewWillAppear里: a.注册了生机勃勃部分键盘和推来推去新闻的通报 b.运营了三个20秒的NSTimer轮询获取闲谈新闻
c.self.chatArray读取数据库的闲聊音信,若是数组为空重临,要是不为空刷新tableview d .若是是从评价页面过来,刷新订单状态
4.看一下轮询音讯的代码:

#pragma mark - 轮询消息
- (void)runLoopMessage {
    SpeakType speaker = [YCChatInfo getSpeakerPassengerBy:self.orderInfo.bigType];
    [[YCReceiveMessageCenter defaultMessageCenter] getMessageListBySpeaker:speaker
                                     isRemote:NO
                                    andPushId:nil];
}

第一句代码是赢得会话类型,这里定义了多个枚举值,首要有以下多少个剧中人物:

//会话类型
enum SpeakType {
    //Business
    YCDriverType     = 11,
    YCPassenger      = 12,
    YCSystem         = 13,      //v5.2.2 增加系统角色
    YCLoctionAutoReply  = 14,  //v5.2.2添加本地自动回复
    YCDriverAutoReply   = 15,  //v5.2.2添加司机自动回复 司机角色
    YCLoctionUpdateVersionReply = 16, //v5.2.2 未知消息类型回复 【提示不支持的消息类型。请升级】
};
typedef NSInteger SpeakType;

接下来依据会话类型去乞求闲谈list接口,然后央浼成功后对数码开展管理:

        //isRemote 点击推送栏消息
        if (response && [response[@"ret_code"] integerValue] == 200) {
            NSArray *array = response[@"result"];
            id topVC = [[YCAppDelegate sharedDelegate] topViewController];
            __block NSString *orderID = nil;
            __block NSString *dType = nil;
            [array enumerateObjectsUsingBlock:^(NSDictionary *result, NSUInteger idx, BOOL *stop) {
                NSString *type = [self controlMessageDispatch:result];
                dType = type;
         //此处省略五百字
            }
        } else {
            DLog(@"轮询数据失败 response = %@, error = %@", response, error);
        }

只要code == 200的时候证实央求成功,然后用数组收取全数的聊天音信,然后用enumerateObjectsUsingBlock方法便利数组里每个成分,每一种成分即一条聊天消息。然后通过controlMessageDispatch来收获音讯的档期的顺序(dType):

typedef NS_ENUM(NSInteger, ClassType) {
   OrderClass = 1,
   ChatClass = 2,
   UserClass = 3,
};

第一个是订单类型音信,第叁个是闲聊类型新闻,第多少个是账户音讯。 假如是订单消息,依据type去推断是怎样处境,然后去发不一致的Notification。假如是闲谈类型把result传入:

- (void)receiveChatMessage:(id)object

方式,然后有二个新闻状态字段kChatRepeatState,假诺kChatRepeatState == 20,表示已读新闻,直接回到。假诺不是,用content伊始化YCChatInfo:

NSDictionary *content = dic[@"content"];
YCChatInfo *item;
item = [[YCChatInfo alloc] initWithDictionary:content];

接下来去看清ChatType,有以下二种:

//聊天 类型
enum ChatType {
    ChatText       = 1,
    ChatImage      = 2,
    ChatAudio      = 3,
    ChatPOI        = 4,
    ChatMix        = 5, //混合内容
    ChatCard       = 6,//v5.2.2卡片消息
    ChatUpdateHint     = 701 //v5.2.2不支持类型升级提示

};
typedef NSInteger ChatType;

假设是语音信息,供给异步先去乞请下载语新闻息,下载完后先出示到分界面上同事置为未读新闻然后再囤积到数据Curry,然后再次回到主线程发NotifactionName:kChatMessageNotification通告谈天分界面采用到闲谈消息,显示到分界面后然后存到数据库中:

[[NSNotificationCenter defaultCenter] postNotificationName:kChatMessageNotification
                                                    object:nil
                                                  userInfo:@{@"chatInfo" : chatInfo}];
[self.chatStore insertChat:chatInfo];

此地上次有个bug,谈天音信去重以往间接选举取不到语音信息,便是因为本身先把新闲聊音讯先插入数据,然后再去发文告,招致往分界面上呈现聊天新闻是连接显得不上去。

假设是文字消息,把state置为MessageRead已读,然后发Notifaction文告闲聊页面,然后存到数据库,假设是任何音信类型,把content改为“不扶植的音讯类型|您的当前版本过低,点击进级客商端”,然后在产生通报,存到数据Curry。

假纵然第三种账户新闻,突显小红点,然后发Notifaction布告viewcontroller新闻宗旨有新信息。 接着获取到dType后

//首先判断是否是推送消息, 且判断该条点击的推送id进入的
                if (isRemote && [pushId isEqualToString:result[@"id"]]) {
                    if (!orderID && ([type isEqualToString:@"new_chat"] ||
                                     [type isEqualToString:@"DRIVER_ARRIVE"] ||
                                     [type isEqualToString:@"RECEPTION_DRIVER"]||
                                     [type isEqualToString:@"SERVICE_DONE"])) {
                        if ([type isEqualToString:@"new_chat"]) {
                            orderID = result[@"content"][@"topic"];
                        } else if (![topVC isKindOfClass:[YCSelectDriverViewController class]] &&
                                   ([type isEqualToString:@"DRIVER_ARRIVE"] ||
                                    [type isEqualToString:@"RECEPTION_DRIVER"] ||
                                    [type isEqualToString:@"SERVICE_DONE"])) {
                                       orderID = result[@"content"][@"order_id"];
                        }
                    }
                }
            }];
            if (orderID) {
                if ([DefaultValueForKey(kShowWelcome) boolValue]) {
                    if (![topVC isKindOfClass:[YCWelcomeVC class]]) {
                        [[NSNotificationCenter defaultCenter] postNotificationName:kRemotePushVC
                                                                            object:nil
                                                                          userInfo:@{@"orderID" : orderID,
                                                                                     @"type":dType}];
                    }
                }
            }

先是剖断是或不是是推送音讯, 且剖断该条点击的推送id步向的,要是orderID不设有且只要type是新谈心音信或驾乘员已达到大概司机接单大概服务截至就进来if判别里,然后在认清type是还是不是闲谈,借使是闲谈orderID是content里的topic字段,就算不是新谈天且当前最顶层ViewController不是YCSelectDriverViewController类且type是司机已达到只怕司机接单或许服务为止就进去if决断里,orderID是content里的order_id字段。
假定orderID存在的动静下先判定应接页面是否显得过,然后再判断当前最顶层ViewController不是款待页类,然后就爆发Notifaction,然后布告view跳转到钦赐的ViewController页面。
当选拔到闲聊音信,经过风度翩翩多种数据管理后,发出公告,然后YCChatViewController里会接到布告调用- (void卡塔尔receiveMessage:(NSNotification *)notification方法:

- (void)receiveMessage:(NSNotification *)notification {
    YCChatInfo *chatInfo  = notification.userInfo[@"chatInfo"];
    //如果此时来的消息不输入当前会话 页面不进行操作
    NSString *string1 = [[NSString alloc] initWithFormat:@"%@", chatInfo.orderID];
    NSString *string2 = [[NSString alloc] initWithFormat:@"%@", self.orderInfo.serverOrderId];
    if (![string1 isEqualToString:string2]) {
        return ;
    }
    NSInteger messageID = chatInfo.messageID;
    YCChatStore *chatStore = [[YCChatStore alloc]init];
    BOOL isNotRepeat = [chatStore selectDBwithMessageID:messageID];
    if (!isNotRepeat) {
        return;
    }
    [self insertRowToTableViewByIndexPath:chatInfo isSend:NO];
}

首先句话是拿到文告里传的闲谈音讯内容,然后拿chatinfo里的orderID和经过得到订单实际情况的接口里拿走的orderID做相比较,要是orderID不均等,直接return。若是直接就去YCChatStore里的selectDBwithMessageID方法里查询数据库是不是有相似的messageID存在,如若存在直接return,假使不设有就插入界面

- (NSIndexPath *)insertRowToTableViewByIndexPath:(YCChatInfo *)chatInfo isSend:(BOOL)isSend {
    NSIndexPath *indexPath;
    [self.chatArray addObject:chatInfo];

    indexPath = [NSIndexPath indexPathForRow:[self.chatArray count] - 1
                                   inSection:0];
    void(^ScrollBlock)() = ^{
        DLog(@"%d",indexPath.row);
        [self.tableView scrollToRowAtIndexPath:indexPath
                              atScrollPosition:UITableViewScrollPositionBottom
                                      animated:YES];
    };
    [self.tableView insertRowsAtIndexPaths:@[indexPath]
                          withRowAnimation:YCTableViewRowAnimationFromBottom
                                completion:^{
                                    if (isSend) {
                                        ScrollBlock();
                                    }
    }];

    if (!isSend) {
        ScrollBlock();
    }

    return indexPath;
}
  • (void)scrollToRowAtIndexPath:(NSIndexPath *卡塔尔国index帕特h atScrollPosition:(UITableViewScrollPosition卡塔尔国scrollPosition animated:(BOOL卡塔尔(قطر‎animated那一个格局是把第多少个indexpath滑动到tableview的最尾部,
  • (void)insertRowsAtIndexPaths:(NSArray *)indexPaths
    withRowAnimation:(YCTableViewRowAnimation)animation
    completion:(void(^)(void))animationCompletion
    这是插入时候的一个动漫效果。
    简言之介绍一下拉扯系统内部全部model、view、controller相关类的名字和功力: MODEL: YCChatInfo: 首要定义了拉家常接口里富有用到字段的概念,聊天相关的枚举信息和推推搡搡音讯的片段BOOL判定。 YCChatStore :首假如对闲谈数据开展数据库的建表、插入、删除、查询、去重、更新等操作。 YCChatRequest :封装了拉家常相关的互连网供给。 YCChatRecord:首借使录音相关的有个别打包,包罗初叶录音、停止录音、获取录音时间长度、音频格式转变、以至经过SessionID获取音频路线。 YCReceiveMessageCenter:相当于NotifactionCenter,是闲谈音讯处理的三个新闻焦点,全部采取的扯淡音讯和出殡和安葬的扯淡信息都会经过MessageCenter管理。 Views: YCChatTableView :继承tableview的类,里边重写了tableview的插入动画,便是每一回来新消息时候的插入动漫。 YCChatBaseCell : 闲扯里富有的cell都连任今后cell(文字、语音,现在还恐怕包含图形、地理地方等等)里边首要定义了拉家常时间的Label、背景图片、头像、司机名、发送时候的loading YCChat奥迪oCell :语音闲聊cell,包蕴播放按键、小红点提示、录音时间label YCChatImageCell :系统中不经常并未动用,可能是为事后聊天能够发图片做筹算 YCChatTextCell : 发送文字闲谈cell YCHeadView :头像cell YCRecordView : 闲聊分界面中按住说话的view YCOrderRecordView :这么些是下单中按住说话的view跟闲扯系统不妨 YCPlayButton :播放音频按键 YCChatDriverAcceptCardCell :5.2.3版本新扩充预约成功卡牌 YCChatJourneyStartCell : 5.2.3版本新扩大司机已起身、司机已就位卡牌 **YCChatUpdatHintCell : 不协助项目,进级提醒

Controllers:
YCChatViewController :谈天的主分界面
YCChatMenuViewController:闲谈右边的开关YCShareJourneyCardVC:预约成功卡牌的详实页YCChatMapVC:闲谈卡牌里的地形图
















**

话非常少说,先看一下做好的社交工具分界面: 首先在StoryBoard里拖了二个UItableView和一个...

1. 预备专业

谈天调整器(ChatViewController卡塔尔(英语:State of Qatar)分界面搭建

ViewController中

1.1 集成SDK

  1. 复制EaseMobSDK到工程,include和lib下只留一个
  2. 增多依赖库
  3. other link flag添加-ObjC

  4. Mark

14.聊天分界面-工具条制版

引进头文件及导入框架

//导入情势:<框架名字/头文件名字>

#import<CoreData/CoreData.h>

#import "Person.h"

#import "AppDelegate.h"

宣示公约

<UITableViewDataSource, UITableViewDelegate>建立UItableView

//评释属性

@property (nonatomic, strong) UITableView *tableview;

//数据源数组

@property (nonatomic, strong) NSMutableArray *dataArray;

//有的时候数据库

@property (nonatomic, strong) NSManagedObjectContext *objectContext;

- (void)viewDidLoad {

[super viewDidLoad];

self.dataArray = [NSMutableArray array];

//获取到大家最最初运用的AppDelegate

AppDelegate *app = (AppDelegate *)[UIApplication sharedApplication].delegate;

self.objectContext = app.managedObjectContext;

//调用查询数据的点子

[self searchAll];

self.tableview = [[UITableView alloc] initWithFrame:[UIScreen mainScreen].bounds style:(UITableViewStyleGrouped)];

self.tableview.backgroundColor = [UIColor redColor];

self.tableview.dataSource = self;

self.tableview.delegate = self;

[self.tableview registerClass:[UITableViewCell class] forCellReuseIdentifier: @"cell"];

[self.view addSubview:  self.tableview];

UIBarButtonItem *batuttonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:(UIBarButtonSystemItemAdd) target:self action:@selector(baButtonItemClicked)];

self.navigationItem.rightBarButtonItem = batuttonItem;

}

//完成点击方法

- (void)baButtonItemClicked

{

//NSEntityDescription: 实体描述类,通过类格局创制

//第三个参数: 表示这一个实体描述类描述的是哪个实体(表名卡塔尔(英语:State of Qatar)

//第1个参数: 表示的是 在context里面创立八个叙述, 告诉context小编要往里面插入叁个object了

NSEntityDescription *description = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:self.objectContext];

//创立八个实体类

//第2个参数: 实体类描述

//第三个参数: 再context里面放入那个类

Person *person = [[Person alloc]initWithEntity:description insertIntoManagedObjectContext:self.objectContext];

int number = arc4random() % 2000;

person.name = [NSString stringWithFormat:@"%d张三", number];

[self insertObject:person];

}

//向coreData中插入一条数据

- (void)insertObject:(Person *)person

{

NSError *error = nil;

//把context保存到地面

//那一个点子推行之后,本地数据才放生改换

[self.objectContext save:&error];

if (error == nil) {

[self.dataArray addObject:person];

NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.dataArray.count - 1 inSection:0];

[self.tableview insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];

}else

{}

}

//找寻全体

- (void)searchAll

{

//成立七个查询操作,查询那么些表里的剧情

NSFetchRequest *request = [[NSFetchRequest alloc]initWithEntityName:@"Person"];

//选拔查询数据

NSError *error = nil;

//让context去履行查询操作,何况再次回到一个结实数组

NSArray *array = [self.objectContext executeFetchRequest:request error:&error];

//判断errar

if (error == nil) {

//假设是 那就放置dataArray

[self.dataArray setArray:array];

[self.tableview reloadData];

}else

{

NSLog(@"查询失利"卡塔尔国;

}

}

//删除

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath

{

//决断一下脚下的编排状态

if (editingStyle == UITableViewCellEditingStyleDelete) {

//获取想要删的数量

Person *person = self.dataArray[indexPath.row];

//在context大校那条数据删除

[self.objectContext deleteObject:person];

NSError *error = nil;

[self.objectContext save:&error];

if (error == nil) {

//先删除数据

[self.dataArray removeObject:person];

//然后更新UI

[self.tableview deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:(UITableViewRowAnimationFade)];

}

}

}

//修改

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

//知道要改哪个人

Person *person = self.dataArray[indexPath.row];

int number = arc4random() % 2000;

person.name = [NSString stringWithFormat:@"%d王五", number];

NSError *error = nil;

[self.objectContext save:&error];

if (error == nil)

{

[self.tableview reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:(UITableViewRowAnimationFade)];

}

}

- (NSInteger )tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

{

return self.dataArray.count;

}

- (NSInteger ) numberOfSectionsInTableView:(UITableView *)tableView

{

return 1;

}

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

{

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];

Person *person = self.dataArray [indexPath.row];

cell.textLabel.text = person.name;

return cell;

}

2.1 主界面

1卡塔尔搭建分界面

2.1.1 登入注册

  1. 新建Sb,搭建UI,完结登陆注册作用
  2. 自动登陆(在签到成功后保存顾客消息,然后下一次运维程序在AppDelegate里推断卡塔尔(قطر‎
  3. 活动连接(互联网连接和App连接)

加上闲扯调节器:到mainstoryboard中找到addressbook的tableview调节器,将cell拖线给叁个uiviewcontroller接纳show,在该调节器导航栏中间拖二个navigationitem,修改名称叫“闲谈界面”,拖一个uiew尺寸与尾部tabar相仿大小,并隐瞒底部的tabar(1.点击调节器bottombar选拔为none.2.点击调整器勾选Hide Bottom Bar

2.1.2 增加好友

  1. 当仁不让增添老铁
  2. 监听基友申请意况
  3. 显示好朋友列表
  4. 基友列表buddyList必要在(自动)登入成功后才有值
  5. buddyList的数额是从 本地数据库获取
  6. 譬如当前有增加好友央求,环信的SDK内部会往数据库的buddy表增添好友记录
  7. 只要程序删除或然客商率先次登入,buddyList表是没记录
    • 要从服务器获取好朋友列表记录
    • 顾客率先次登陆后,自动从服务器获取好朋友列表
  8. 老铁申请被允许后刷新基友列表
  • 在“好朋友加多乞请同意”代理里积极调用从服务器获取基友列表的Api给密友列表数据源重新赋值然后刷新表格
  1. 吸收接纳别人的知心人申请
  2. 去除老铁
  3. 监听被删除亲密的朋友

on Push卡塔尔(قطر‎。(注意输入框为textview),中间部分拖贰个tableview,自动构造,设置代理,注意tableview中有个特性,拖动时隐蔽键盘(scrollview-keyboard-选用dissmiss on drag)

2.1.3 退出登陆

自定义该谈天调控器:chatviewcontroller,将storyboard中调控器class改为该调节器的类名。

2.2 闲聊分界面(发送文字)

2卡塔尔(قطر‎完毕键盘退出、弹出,工具栏紧链接效率:调节器代码如下:

2.2.1 定制底部工具条

  1. 搭建UI
  2. 点击输入框弹出键盘,改过约束上移toolBarView的可观(用了IQKeyboardManager要先禁止使用,同一时间一贯在Sb中给中间的tableview设置keyboard→DismissOnDrag

//1.将工具条尾巴部分的羁绊拖线为该调节器的性质。

2.2.2 cell的排版

@property(weak,nonatomic)IBOutletNSLayoutConstraint*chatInputBottomConstant;

1. 接收方

  • Label和背景imageView四条边Edges约束设置
  • 背景imageView的拉伸
  • Label中度随文字多少变化
    • numberOfLines = 0
    • 升幅约束改为More than
    • Label要突显多行文字只增添下边三个autolayout和numberofline是远远不够的!!!一定还要设置preferredMaxLayoutWidth那本性情!!!那么那是为啥呢?
    • 当label文字比较多的时候,会意识文字最左边有的地点空余了不知凡几,那就是难题所在
    • 在xib中装置Label的束缚,什么间隔父控件左侧10,间距父控件右侧10,然而对于文字大概单词,在终极相当不足本身显示的时候,会活动换行
    • 自动换行之后,问题就来了!本来在预测第3行就能够全体展现完文字,由于活动换行,结果第4行才全体出示完,那就产生实际呈现的惊人比测度的可观越来越高,所以在显示器上来看当Label里文字或单词在结尾现身了电动换行时,每种cell最上面就无法一心显示Label的内容
    • 由此说要求设置preferredMaxLayoutWidth来告诉系统Label的首要推荐宽度,而且这个preferredMaxLayoutWidth的初期级高于于autolayout宽度节制。能够这么明白,autolayout只是安装了Label的羁绊,而preferredMaxLayoutWidth设置了Label和个中间文字的牢笼

//2.viewdidload中监听键盘弹出/回方法

2. 发送方

和吸收接纳方cell是两种cell,可是公共二个m文件

//1卡塔尔(قطر‎.监听键盘弹出,把inputToolbar(输入工具条卡塔尔国往上移

3. 乘除cell的冲天(这里是用的sb)

  1. 在chatCell里提供二个划算高度的方法
/** 返回cell的高度*/
-(CGFloat)cellHeghit{
    //1.重新布局子控件
    [self layoutIfNeeded];
    return 5 + 10 + self.messageLabel.bounds.size.height + 10 + 5;
}
  1. 在调控器里定义一个非常用作计算中度的chatCell
/** 计算高度的cell工具对象 */
@property (nonatomic, strong) XMGChatCell *chatCellTool;
  1. 在viewDidLoad里给那个chatCellTool赋值
// 给计算高度的cell工具对象,这里ReceiverCell也可以写SenderCell,随便哪个都行,因为二者都是存在的
    self.chatCellTool = [self.tableView dequeueReusableCellWithIdentifier:ReceiverCell];
  1. 在回到中度的代理方法里总结出中度
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    // 设置label的数据
#warning 计算高度与前,一定要给messageLabel.text赋值
    self.chatCellTool.messageLabel.text = self.dataSources[indexPath.row];
    return [self.chatCellTool cellHeghit];
}

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(kbWillShow:)name:UIKeyboardWillShowNotificationobject:nil];

2.2.3 发送闲聊信息

//2).监听键盘退出,inputToolbar苏醒原来之处

1. 以换行符监听textView的发送动作

  • 改变textView的returnKeyType为UIReturnKeySend
  • 出殡前要去掉换行符

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(kbWillHide:)name:UIKeyboardWillHideNotificationobject:nil];

2. 监听Segue的跳转,传递buddy

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{

    //往聊天控制器 传递一个 buddy的值
    id destVC = segue.destinationViewController;
    if ([destVC isKindOfClass:[ChatController class]]) {
        //获取点击的行
        NSInteger selectedRow = [self.tableView indexPathForSelectedRow].row;

        ChatController *chatVc = destVC;
        chatVc.buddy = self.buddyList[selectedRow];
    }

}

//3.落到实处监听方法

3. 发送新闻

#pragma mark - UITextView代理
-(void)textViewDidChange:(UITextView *)textView{
    NSLog(@"%@",textView.text);

    // 监听Send事件--判断最后的一个字符是不是换行字符
    if ([textView.text hasSuffix:@"n"]) {
        NSLog(@"发送操作");
        [self sendMessage:textView.text];
        // 清空textView的文字
        textView.text = nil;   
    }    
}
-(void)sendMessage:(NSString *)text{
    //消息 = 消息头 + 消息体
#warning 每一种消息类型对象不同的消息体
    //    EMTextMessageBody 文本消息体
    //    EMVoiceMessageBody 录音消息体
    //    EMVideoMessageBody 视频消息体
    //    EMLocationMessageBody 位置消息体
    //    EMImageMessageBody 图片消息体

    NSLog(@"要发送给 %@",self.buddy.username);

    //    return;
    // 创建一个聊天文本对象
    EMChatText *chatText = [[EMChatText alloc] initWithText:text];

    //创建一个文本消息体
    EMTextMessageBody *textBody = [[EMTextMessageBody alloc] initWithChatObject:chatText];

    //1.创建一个消息对象
    EMMessage *msgObj = [[EMMessage alloc] initWithReceiver:self.buddy.username bodies:@[textBody]];

    // 2.发送消息
    [[EaseMob sharedInstance].chatManager asyncSendMessage:msgObj progress:nil prepare:^(EMMessage *message, EMError *error) {
        NSLog(@"准备发送消息");
    } onQueue:nil completion:^(EMMessage *message, EMError *error) {
        NSLog(@"完成消息发送 %@",error);
    } onQueue:nil];

}

#pragma mark键盘展现时会触发的办法

2.2.4 加载本地闲谈记录

  1. 在viewDidload里加载本地数据库谈心记录(MessageV1)
-(void)loadLocalChatRecords{
    // 要获取本地聊天记录使用 会话对象
    EMConversation *conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:self.buddy.username conversationType:eConversationTypeChat];

    // 加载与当前聊天用户所有聊天记录
    NSArray *messages = [conversation loadAllMessages];

    for (id obj in messages) {
        NSLog(@"%@",[obj class]);
    }

    // 添加到数据源
    [self.dataSources addObjectsFromArray:messages];
}
  1. 在cellforrow方法里依据EMMessage的from属性推断是发送方依然选用方的消息
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    //1.先获取消息模型
    EMMessage *message = self.dataSources[indexPath.row];
    //    EMMessage
    /* from:xmgtest1 to:xmgtest7 发送方(自己)
     * from:xmgtest7 to:xmgtest1 接收方 (好友)
     */
    ChatCell *cell = nil;
    if ([message.from isEqualToString:self.buddy.username]) {//接收方
        cell = [tableView dequeueReusableCellWithIdentifier:ReceiverCell];
    }else{//发送方
        cell = [tableView dequeueReusableCellWithIdentifier:SenderCell];
    }
    //显示内容
    cell.message = message;
    return cell;
}
  1. 点击发送新闻后刷新闲谈记录,把音讯突显在顶端
// 3.把消息添加到数据源,然后再刷新表格
    [self.dataSources addObject:msgObj];
    [self.tableView reloadData];
// 4.把消息显示在顶部
    [self scrollToBottom];
  1. 经受消息并呈现

-(void)kbWillShow:(NSNotification*)noti{

2.2.5 完备输入框

  1. 让输入框textView高度随文字内容改动,注意最后让光标回到原来的地点的技能
#pragma mark - UITextView代理
-(void)textViewDidChange:(UITextView *)textView{
    NSLog(@"contentOffset %@",NSStringFromCGPoint(textView.contentOffset));
    // 1.计算TextView的高度,
    CGFloat textViewH = 0;
    CGFloat minHeight = 33;//textView最小的高度
    CGFloat maxHeight = 68;//textView最大的高度
    // 获取contentSize的高度
    CGFloat contentHeight = textView.contentSize.height;
    if (contentHeight < minHeight) {
        textViewH = minHeight;
    }else if (contentHeight > maxHeight){
        textViewH = maxHeight;
    }else{
        textViewH = contentHeight;
    }
    // 2.监听Send事件--判断最后的一个字符是不是换行字符
    if ([textView.text hasSuffix:@"n"]) {
        NSLog(@"发送操作");
        [self sendMessage:textView.text];
        // 清空textView的文字
        textView.text = nil;
        // 发送时,textViewH的高度为33
        textViewH = minHeight;   
    }
    // 3.调整整个InputToolBar 高度
    self.inputToolBarHegihtConstraint.constant = 6 + 7 + textViewH;
    // 加个动画
    [UIView animateWithDuration:0.25 animations:^{
        [self.view layoutIfNeeded];
    }];
    // 4.记光标回到原位
#warning 技巧
    [textView setContentOffset:CGPointZero animated:YES];
    [textView scrollRangeToVisible:textView.selectedRange];
}
  1. 给输入框加背景图片

//1.到手键盘高度

2.3 语音

//1.1获得键盘结束时候的地点

2.3.1 发送语音

  1. 搭建UI
  2. 录音键的两种动作
  • 按下touchDown
  • 抬起touchUpInside
  • 从按键外面松手撤除录音touchUpOutSide
  1. 拖入几个环信的录音库,import文件
  2. 写发送API

CGRectkbEndFrm = [noti.userInfo[UIKeyboardFrameEndUserInfoKey]CGRectValue];

2.3.2 播放语音

  1. 展现语音UI(这里是用富文本实现的)
  2. 播音动漫
  3. 那边在真机播放录音的时候崩了,原本是IOS10的权限难点,在info.plist里增多录音的权限。上边把两种常用权限列出来供之后备用
    //相机
    <key>NSCameraUsageDescription</key>    
    <string>cameraDesciption</string>
    //相册
    <key>NSPhotoLibraryUsageDescription</key>    
    <string>photoLibraryDescription</string>
    //通讯录
    <key>NSContactsUsageDescription</key>    
    <string>contactsDesciption</string>
    //麦克风
    <key>NSMicrophoneUsageDescription</key>    
    <string>microphoneDesciption</string>
  1. 滑动的时候停止播放语音

CGFloatkbHeight = kbEndFrm.size.height;

2.3 图片的出殡和安葬和展现

  • 那边真机调用相册也蒙受上面包车型大巴标题,要在info.plist加多属性
  • 【注】这里cell重用时要求先移除图片(懒加载必需用strong)

//2.更改inputToolbar尾巴部分封锁

2.4 时间cell

self.chatInputBottomConstant.constant= kbHeight;

光阴的显得

  1. 岁月显示准绳
1.同一分中内的消息,只显示一个时间
    /*
     15:52
     msg1 15:52:10
     msg2 15:52:08
     msg2 15:52:02
     */
2./*今天:时:分 (HH:mm)
      *昨天: 昨天 + 时 + 分 (昨天 HH:mm)
      *昨天以前:(前天) 年:月:日 时 分(2015-09-26 15:27)
 */
  1. 多少源里的每条数据都急需基于展现法规剖断要不要先插入二个日子,然后在cellforrow里依照数量源类型判别要不要展现时间

//增加卡通片

日子的计算

  1. 先实现今日、前几天和以前的计量,然后每便往数据源数组里增添数据都要先举办判别
  2. 先是步完毕后再落实时间突显准绳朝气蓬勃就特别轻便了。因为自然时间正是只准确到分钟,然后法规生龙活虎也是千篇生机勃勃律分钟内时间不显得,所以那个时候只必要对第一步的时日过滤,进行判别,在近期controller加个时间字符串属性,当前多少个数据源的光阴和上个数据源的光阴开展相比,不相似就增进,相像就保留
  3. 以身作则中判断明日的算法是错的,需求再行写三个

[UIViewanimateWithDuration:0.25animations:^{

2.5 会话分界面

  1. 显示历史会话记录
  2. 未读音讯(更新外人发来的新闻)
  3. 增加外人发来的新闻
  4. 设置音讯已读

[self.viewlayoutIfNeeded];

}];

}

#pragma mark键盘退出时会触发的办法

-(void)kbWillHide:(NSNotification*)noti{

//inputToolbar苏醒原来的地点

self.chatInputBottomConstant.constant=0;

}

//4.注销监听者

-(void)dealloc{

[[NSNotificationCenterdefaultCenter]removeObserver:self];

}

15.闲谈界面-接收方cell的制版

因此分析,cell有二种档期的顺序:选择方cell、发送方cell、时间cell。

在刚刚拖入的tableview上拖三个cell重命名称为receivecell,再改cell中拖入控件并自动布局,给cell设置重用标记为receivecell

留意:构造音信框:理念:底部为图片,上边为label,先结构label,然后布局imageview,让他与label大小同等,然后改过约束使iamgeview周边都比label附近大学一年级些。

A.构造label:Label构造为离开顶端15,左边20。换行:点击label-lines = 0、(设置label最小幅面)点击尺子- preferred width = 242勾选,回车

B.结构uiiamgeview:cell中拖多少个UIimageview,从左侧的列表中找到该imageview,拖到label的前边,同期选中label、iamgeview、设置四边距都对齐限定,然后update,给iamgeview增添背景图片,图片拉伸:点击imageview-streching-x:0.5/y:0.7,其他都为0。找到iamgeview的保有节制,给周边限定分别调11个区间大小。

自定义cell,view-ChatCell,将刚才storyboard中的cell的class改为此类。将地点十一分label拖线到.h文件(必得)为属性

调控器中数据源和代办的不二秘诀完结如下(测量检验而已卡塔尔(英语:State of Qatar):

-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{

return20;

}

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{

return200;

}

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

staticNSString*ID =@"ReceiverCell";

ChatCell*cell = [tableViewdequeueReusableCellWithIdentifier:ID];

//突显内容

cell.chatLabel.text=@"asrqwerqwerqwerqwerqwfaskdjlfalsk;dfjalksjdflaksjdfa;sjdfklajsdkfljasfkal;sdkfjalksjdfa;jsdflkajsdf;lajskdf;las";

returncell;

}

16.谈天界面-发送方cell的排版

1卡塔尔国.tableview中再拖贰个cell,同理搭建sendcell(注意:将label脱线到cell中的同一个属性中卡塔尔国

2卡塔尔国.设置cell的莫斯中国科学技术大学学:在自定义cell中贯彻计算cell的惊人)

//特地用来测算中度的两个cell(注意理解)

#import

staticNSString*ReceiverCell =@"ReceiverCell";

staticNSString*SenderCell =@"SenderCell";

@interfaceChatCell :UITableViewCell

@property(weak,nonatomic)IBOutletUILabel*chatLabel;

-(CGFloat)cellHeghit;

@end

#import"ChatCell.h"

@implementationChatCell

/**返回cell的高度*/

-(CGFloat)cellHeghit{

//1.双重布局子控件

[selflayoutIfNeeded];

return5+10+self.chatLabel.bounds.size.height+10+5;

}

@end

3卡塔尔国.调节器中落到实处的不二秘技

a.增添属性

@property(weak,nonatomic)IBOutletUITableView*tableView;

/**数据源*/

@property(nonatomic,strong)NSMutableArray*dataSources;

/**算算高度的cell工具对象(便是三个工具,给自个儿文字长度作者就能够计算低度卡塔尔(قطر‎*/

@property(nonatomic,strong)ChatCell*chatCellTool;

b.viewdidload开始化数据源

-(NSMutableArray*)dataSources{

if(!_dataSources) {

_dataSources= [NSMutableArrayarray];

}

return_dataSources;

}

//起先化数(多数少个长的卡塔尔据

[self.dataSourcesaddObject:@"xcsafasdffsadfa"];

[self.dataSourcesaddObject:@"xcsafasdfsadxcssafasdfsadfafa"];

[self.dataSourcesaddObject:@"xcsafasdfxcsaadfasadfa"];

//给总括中度的cell工具对象赋值(正是起头化学工业具对象,也得感到sendcell卡塔尔国

self.chatCellTool= [self.tableViewdequeueReusableCellWithIdentifier:ReceiverCell];

c.重新完毕数据源方法

-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{

returnself.dataSources.count;

}

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{

//设置label的数据

#warning计算中度与前,应当要给chatLabel.text赋值

self.chatCellTool.chatLabel.text=self.dataSources[indexPath.row];

return[self.chatCellToolcellHeghit];

}

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

ChatCell*cell =nil;

if(indexPath.row%2==0卡塔尔(قطر‎ {//发送方的cell

cell = [tableViewdequeueReusableCellWithIdentifier:SenderCell];

}else{//接纳发方的cell

cell = [tableViewdequeueReusableCellWithIdentifier:ReceiverCell];

}

//展现内容

cell.chatLabel.text=self.dataSources[indexPath.row];

returncell;

}

新闻管理

音讯:IM人机联作实体,在SDK中对应的项目是EMMessage。EMMessage由EMMessageBody组成.

总计:与新闻相关的互联网乞请都用到[[EMClientsharedClient].chatManager闲谈管理者

拿到一位的对话列表用EMConversation类

17.闲聊分界面-发送闲谈音讯

步骤:

在mainstoryboard中找到谈天界面包车型大巴输入框textView,点击-return-send

监听该send事件:拖线该text田野的代办到闲聊调整器(ChatViewController)。调节器据守代理(UITextViewDelegate),并促成代理方法

导入头文件:#import "EMSDK.h"(用多了足以增添到pch文件中)

1卡塔尔国.给该调整器加多多少个外界属性

//要发送给旁人的名字

@property(nonatomic,copy)NSString*buddy;

2卡塔尔国.在通信录调节器(AddressBookViewController)中传值,代码如下:

-(void)prepareForSegue:(UIStoryboardSegue*)segue sender:(id)sender{

//往闲聊调节器传递三个buddy的值

iddestVC = segue.destinationViewController;

if([destVCisKindOfClass:[ChatViewControllerclass]]) {

//获取点击的行

NSIntegerselectedRow = [self.tableViewindexPathForSelectedRow].row;

ChatViewController*chatVc = destVC;

chatVc.buddy=self.boddyList[selectedRow];

}

}

3卡塔尔(英语:State of Qatar).闲聊调控器(ChatViewController)中发送新闻代码如下

#pragma mark -UITextViewDelegate

-(void)textViewDidChange:(UITextView*)textView{

//监听Send事件--剖断最后的三个字符是或不是换行字符(因为点击send时,text田野同志会换行)

if([textView.texthasSuffix:@"n"]) {

NSLog(@"发送操作"卡塔尔国;

[selfsendMessage:textView.text];

//清空textView的文字

textView.text=nil;

}

}

//发送消息

-(void)sendMessage:(NSString*)text{

//把最后多个换行字符去除

#warning换行字符只占用叁个长度

text = [textsubstringToIndex:text.length-1];

//消息=消息头+消息体

#warning每风度翩翩种新闻类型对象不一样的音讯体

//EMTextMessageBody:文字

//EMImageMessageBody:图片

//EMLocationMessageBody:位置

//EMVoiceMessageBody:语音

//EMVideoMessageBody:视频

//EMFileMessageBody:文件

//EMCmdMessageBody:透传

//1.创办文字新闻体

EMTextMessageBody*body = [[EMTextMessageBodyalloc]initWithText:text];

NSString*from = [[EMClientsharedClient]currentUsername];

//2.生成Message新闻指标

EMMessage*message = [[EMMessagealloc]initWithConversationID:self.buddyfrom:fromto:self.buddybody:bodyext:nil];

message.chatType=EMChatTypeChat;//设置为单聊音讯

//新闻类型为:

//EMChatTypeChat:设置为单聊音信

// EMChatTypeGroupChat:设置为群聊消息

//EMChatTypeChatRoom:设置为闲谈室音讯

//3.出殡和安葬消息

//发送全数品种的音讯都用那个接口,只是音信类型不相同

[[EMClientsharedClient].chatManagersendMessage:messageprogress:^(intprogress) {

}completion:^(EMMessage*message,EMError*error) {

NSLog(@"实现音讯发送%@",error卡塔尔(قطر‎;

}];

// 4.把音信增多到数据源,然后再刷新表格(发送完音信立刻突显)

[self.dataSourcesaddObject:message];

[self.tableViewreloadData];

// 5.把音讯突显在最上端(发送完新闻自动滚动到键盘顶端)

[selfscrollToBottom];

}

-(void)scrollToBottom{

//1.获得最后意气风发行

if(self.dataSources.count==0) {

return;

}

NSIndexPath*lastIndex = [NSIndexPathindexPathForRow:self.dataSources.count-1inSection:0];

[self.tableViewscrollToRowAtIndexPath:lastIndexatScrollPosition:UITableViewScrollPositionBottomanimated:YES];

}

18.闲谈分界面-增多本地闲聊记录

1卡塔尔(英语:State of Qatar).在闲谈调节器中的viewdidload方法中增加当前navigation的title为好友的名字,加载本地闲谈记录

//彰显亲密的朋友的名字

self.title=self.buddy;

//加载本地数据库闲扯记录(MessageV1)

[selfloadLocalChatRecords];

-(void)loadLocalChatRecords{

//要博得本地闲聊记录使用会话对象

//获取三个会话

//EMConversationTypeChat单聊会话

//EMConversationTypeGroupChat群聊会话

//EMConversationTypeChatRoom谈天室会话

EMConversation*conversation = [[EMClientsharedClient].chatManagergetConversation:self.buddytype:EMConversationTypeChatcreateIfNotExist:YES];

//加载与当前闲谈客户具有闲谈记录

// fromUser:若传亲密的朋友名字,则只会加载基友发的谈心记录,若为nil加载两方的

longlongtimestamp = [[NSDatedate]timeIntervalSince1970] *1000+1;

[conversationloadMessagesWithType:EMMessageBodyTypeTexttimestamp:timestampcount:100fromUser:nilsearchDirection:EMMessageSearchDirectionUpcompletion:^(NSArray*aMessages,EMError*aError) {

//aMessages内部为EMMessage对象

//增添到数据源

[self.dataSourcesaddObjectsFromArray:aMessages];

[self.tableViewreloadData];

}];

}

2卡塔尔(قطر‎.在自定义cellChatCell中增多外界模型属性,并促成set方法,封装

/**新闻模型,内部set方法显示文字*/

@property(nonatomic,strong)EMMessage*message;

-(void)setMessage:(EMMessage*)message{

_message= message;

// 1.获取音讯体

idbody = message.body;

if([bodyisKindOfClass:[EMTextMessageBodyclass]]卡塔尔国 {//文本音信

EMTextMessageBody*textBody = body;

self.chatLabel.text= textBody.text;

}elseif([bodyisKindOfClass:[EMVoiceMessageBodyclass]]卡塔尔(قطر‎{//语音音讯

self.chatLabel.text=@"【语音】";

}

else{

self.chatLabel.text=@"未知类型";

}

}

3卡塔尔(قطر‎.在闲谈调控器中期维修改tableview的数据源方法

-(NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section{

returnself.dataSources.count;

}

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath{

//设置label的数据

NSLog(@"%@",self.dataSources[indexPath.row]);

// 1.赢得新闻模型

EMMessage*msg =self.dataSources[indexPath.row];

self.chatCellTool.message= msg;

return[self.chatCellToolcellHeghit];

}

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

//1.先获取音信模型

EMMessage*message =self.dataSources[indexPath.row];

ChatCell*cell =nil;

if([message.fromisEqualToString:self.buddy]) {//接收方

cell = [tableViewdequeueReusableCellWithIdentifier:ReceiverCell];

}else{//发送方

cell = [tableViewdequeueReusableCellWithIdentifier:SenderCell];

}

//显示内容

cell.message= message;

returncell;

}

29.闲谈分界面-监听新闻回复(将对方发的新闻随时突显在当下聊天分界面)

闲谈调整器中的viewdidload中安装闲聊微处理器代理并据守左券EMChatManagerDelegate

[[EMClientsharedClient].chatManageraddDelegate:selfdelegateQueue:nil];

//实今世理方法

#pragma mark -EMChatManagerDelegate

//收到一条以上音信

- (void)messagesDidReceive:(NSArray*)aMessages{

for(EMMessage*messageinaMessages) {

#warning from一定等于当前闲聊顾客本事够刷新数据(当test1 - test7两者聊天时,test8发过来的消息无法显得在该闲聊记录分界面)

if([message.fromisEqualToString:self.buddy]) {

//1.把接纳的音信增多到数据源

[self.dataSourcesaddObject:message];

//2.刷新表格

[self.tableViewreloadData];

//3.出示数据到底层

[selfscrollToBottom];

}

}

}

20.周全闲聊输入框

福衢寿车输入框自动改换高度:

1卡塔尔国.找到mainstoryboard中的闲聊调控器分界面包车型地铁ChatInputToolBar找到她的中度属性,并拖线到闲谈调节器成为其品质

@property(weak,nonatomic)IBOutletNSLayoutConstraint*inputbarHeightConstant;

2卡塔尔国.在闲谈调控器ChatViewController中的监听文字改造的章程中拉长:

#pragma mark -UITextViewDelegate

-(void)textViewDidChange:(UITextView*)textView{

//监视textView.contentOffset的变化

NSLog(@"contentOffset %@",NSStringFromCGPoint(textView.contentOffset));

// 1.总结TextView的可观,调解总体intputbar的可观

CGFloattextViewH =0;

CGFloatminHeight =33;//textView最小的中度

CGFloatmaxHeight =68;//textView最大的惊人

//获取contentSize的高度(因为textView继承自scrollview)

CGFloatcontentHeight = textView.contentSize.height;

if(contentHeight < minHeight) {

textViewH = minHeight;

}elseif(contentHeight > maxHeight){

textViewH = maxHeight;

}else{

textViewH = contentHeight;

}

// 2.监听Send事件--推断最终的叁个字符是或不是换行字符(因为点击send时,text田野(field卡塔尔(英语:State of Qatar)会换行)

if([textView.texthasSuffix:@"n"]) {

NSLog(@"发送操作"卡塔尔(قطر‎;

[selfsendMessage:textView.text];

//清空textView的文字

textView.text=nil;

//发送时,textViewH的中度为33

textViewH = minHeight;

}

// 3.调动总体InputToolBar中度

self.inputbarHeightConstant.constant=6+7+ textViewH;

//加个卡通

[UIViewanimateWithDuration:0.25animations:^{

[self.viewlayoutIfNeeded];

}];

// 4.记光标回到原来的地点

#warning技巧

[textViewsetContentOffset:CGPointZeroanimated:YES];

[textViewscrollRangeToVisible:textView.selectedRange];

}

3卡塔尔(قطر‎.给textview加多背景:

在textview前边加三个背景图片(imageview),在mainstoryboard中找到ChatInputToolBar,往里面拖三个imageview,设置其限定与textview同样,加多背景图片(并设置拉伸效果),将textView的背景象改为透明

21.发送语音

1卡塔尔(英语:State of Qatar).点击侧边包车型客车迈克风开关,输入框变为发语音框,自动布局

在mainstoryboard中的闲谈调整器界面包车型客车ChatInputToolBar中拖五个button,间接盖住textView上边,纠正文字为“按住说话”,订正高亮时的文字为“甩手拓送”,设置约束,固定中度,选用暗中认可为遮掩,拖线监听侧边的迈克风开关:

//语音框

@property(weak,nonatomic)IBOutletUIButton*recordBtn;

//监听语音点击开关

- (IBAction)voiceAction:(id)sender {

//1.突显录音开关

self.recordBtn.hidden= !self.recordBtn.hidden;

self.textView.hidden= !self.textView.hidden;

}

2卡塔尔(قطر‎.到环信官方demo中EaseUI-中找到DeviceHelper导入框架,EaseLocalDefine.h/EaseUIResource.bundle也导入框架

推动项指标Lib文件。再改调整器中程导弹入头文件#import"EMCDDeviceManager.h"

拖线监听语音框,监听按下去时,动作(选中该按键,),找到点下触发,拖线监听:

#pragma mark按键点下去开头录音

//开头录音

- (IBAction)beginVoiceAction:(id)sender {

//文件名以时间命名(根据时间概念文件的名字)

//filename:录音就要贮存的文本(自动存放沙盒)

intx =arc4random() %100000;

NSTimeIntervaltime = [[NSDatedate]timeIntervalSince1970];

NSString*fileName = [NSStringstringWithFormat:@"%d%d",(int)time,x];

NSLog(@"按键点下去伊始录音"卡塔尔国;

//这一个主意,正是可怜框架(DeviceHelper卡塔尔(قطر‎中的方法

[[EMCDDeviceManagersharedInstance]asyncStartRecordingWithFileName:fileNamecompletion:^(NSError*error) {

if(!error) {

NSLog(@"初阶录音成功"卡塔尔;

}

}];

}

#pragma mark手指从开关范围内松手得了录音

//甘休录音

- (IBAction)endVoiceAction:(id)sender {

[[EMCDDeviceManagersharedInstance]asyncStopRecordingWithCompletion:^(NSString*recordPath,NSIntegeraDuration,NSError*error) {

//recordPath:录音的不二等秘书诀

//aDuration:录音的时间长度

if(!error) {

NSLog(@"录音成功"卡塔尔国;

NSLog(@"%@",recordPath);

//发送语音给服务器

[selfsendVoice:recordPathduration:aDuration];

}else{

NSLog(@"== %@",error);

}

}];

}

#pragma mark手指从按键外面松手打消录音

//打消录音

- (IBAction)cancelVoiceAction:(id)sender {

[[EMCDDeviceManagersharedInstance]cancelCurrentRecording];

}

#pragma mark发送语音消息

//发送语音

-(void)sendVoice:(NSString*)recordPath duration:(NSInteger)duration{

//1.创制语音音讯体

EMVoiceMessageBody*body = [[EMVoiceMessageBodyalloc]initWithLocalPath:recordPathdisplayName:@"语音"];

body.duration= (int)duration;

NSString*from = [[EMClientsharedClient]currentUsername];

//2.生成voice音信对象

EMMessage*voice = [[EMMessagealloc]initWithConversationID:self.buddyfrom:fromto:self.buddybody:bodyext:nil];

voice.chatType=EMChatTypeChat;//设置为单聊新闻

//3.发送新闻

//发送全数连串的音信都用这几个接口,只是信息类型不相同

[[EMClientsharedClient].chatManagersendMessage:voiceprogress:^(intprogress) {

}completion:^(EMMessage*message,EMError*error) {

NSLog(@"完毕新闻发送%@",error卡塔尔;

}];

// 4.把信息增加到数据源,然后再刷新表格(发送完音信马上显示)

[self.dataSourcesaddObject:voice];

[self.tableViewreloadData];

// 5.把音信展现在最上部(发送完新闻自动滚动到键盘顶上部分)

[selfscrollToBottom];

}

22.广播语音

1卡塔尔(英语:State of Qatar).//突显语音的款式为图片Gavin字,在ChatCell中得以完结情势:

#pragma mark重返语音富文本

-(NSAttributedString*)voiceAtt{

//成立一个可变的富文本

NSMutableAttributedString*voiceAttM = [[NSMutableAttributedStringalloc]init];

// 1.接收方:富文本=图片+时间

if([self.reuseIdentifierisEqualToString:ReceiverCell]) {

// 1.1选择方的话音图片

UIImage*receiverImg = [UIImageimageNamed:@"chat_receiver_audio_playing_full"];

// 1.2成立图片附属类小零件

NSTextAttachment*imgAttachment = [[NSTextAttachmentalloc]init];

imgAttachment.image= receiverImg;

imgAttachment.bounds=CGRectMake(0, -7,30,30);

// 1.3图片富文本

NSAttributedString*imgAtt = [NSAttributedStringattributedStringWithAttachment:imgAttachment];

[voiceAttMappendAttributedString:imgAtt];

// 1.4.创办时间富文本

//获取时间

EMVoiceMessageBody*voiceBody = (EMVoiceMessageBody*)self.message.body;

NSIntegerduration = voiceBody.duration;

NSString*timeStr = [NSStringstringWithFormat:@"%ld'",duration];

NSAttributedString*timeAtt = [[NSAttributedStringalloc]initWithString:timeStr];

[voiceAttMappendAttributedString:timeAtt];

}else{

// 2.发送方:富文本=时间+图片

// 2.1拼凑时间

//获取时间

EMVoiceMessageBody*voiceBody = (EMVoiceMessageBody*)self.message.body;

NSIntegerduration = voiceBody.duration;

NSString*timeStr = [NSStringstringWithFormat:@"%ld'",duration];

NSAttributedString*timeAtt = [[NSAttributedStringalloc]initWithString:timeStr];

[voiceAttMappendAttributedString:timeAtt];

// 2.1拼接图片

UIImage*receiverImg = [UIImageimageNamed:@"chat_sender_audio_playing_full"];

//制造图片附属类小零器件

NSTextAttachment*imgAttachment = [[NSTextAttachmentalloc]init];

imgAttachment.image= receiverImg;

imgAttachment.bounds=CGRectMake(0, -7,30,30);

//图片富文本

NSAttributedString*imgAtt = [NSAttributedStringattributedStringWithAttachment:imgAttachment];

[voiceAttMappendAttributedString:imgAtt];

}

return[voiceAttMcopy];

}

2卡塔尔.在该格局中该setMessage:(EMMessage*)message:

self.chatLabel.text = @"【语音】";

self.chatLabel.attributedText= [selfvoiceAtt];

3卡塔尔(قطر‎.给语音讯息加多点拍手势,并监听方法:(在mainstoryboard中找到,新闻label张开客户交互作用)

//导入头文件:#import"EMCDDeviceManager.h"#import"AudioPlayTool.h"

-(void)awakeFromNib{

//在这办法做一些伊始化操作

// 1.给label增多敲拍掌势

UITapGestureRecognizer*tap = [[UITapGestureRecognizeralloc]initWithTarget:selfaction:@selector(messageLabelTap:)];

[self.chatLabeladdGestureRecognizer:tap];

}

#pragma mark messagelabel点击的触及方法

-(void)messageLabelTap:(UITapGestureRecognizer*)recognizer{

NSLog(@"%s",__func__);

//播放语音

//独有当前的种类是为语音的时候才播放

//1.获取音讯体

idbody =self.message.body;

if([bodyisKindOfClass:[EMVoiceMessageBodyclass]]) {

NSLog(@"播放语音"卡塔尔(قطر‎;

BOOLreceiver = [self.reuseIdentifierisEqualToString:ReceiverCell];

[AudioPlayToolplayWithMessage:self.messagemsgLabel:self.chatLabelreceiver:receiver];

}

}

4卡塔尔(英语:State of Qatar).写八个工具类来播音语音goup –chart-Tool-奥迪(Audi卡塔尔(قطر‎oPlayTool

#import

#import"EMSDK.h"

@interfaceAudioPlayTool :NSObject

+(void)playWithMessage:(EMMessage*)msg msgLabel:(UILabel*)msgLabel receiver:(BOOL)receiver;

@end

#import"AudioPlayTool.h"

#import"EMCDDeviceManager.h"

//用imageview播放动漫(好好钻研卡塔尔(قطر‎

staticUIImageView*animatingImageView;//正在施行动漫的ImageView

@implementationAudioPlayTool

+(void)playWithMessage:(EMMessage*)msg msgLabel:(UILabel*)msgLabel receiver:(BOOL)receiver{

//把原先的动漫移除

[animatingImageViewstopAnimating];

[animatingImageViewremoveFromSuperview];

//1.广播语音

//获取语音路线

EMVoiceMessageBody*voiceBody = (EMVoiceMessageBody*) msg.body;

// localPath:本地音频路线

// remotePath:服务器音频路线

//本地口音文件路线

NSString*path = voiceBody.localPath;

//假诺本地口音文件不设有,使用服务器语音

NSFileManager*manager = [NSFileManagerdefaultManager];

if(![managerfileExistsAtPath:path]) {

path = voiceBody.remotePath;

}

//播放语音

[[EMCDDeviceManagersharedInstance]asyncPlayingWithPath:pathcompletion:^(NSError*error) {

NSLog(@"语音播放完结%@",error卡塔尔国;

//移除动漫

[animatingImageViewstopAnimating];

[animatingImageViewremoveFromSuperview];

}];

//2.加多动画片(点击语新闻息时有动漫)让UIImageView播放动漫、动漫的里边贯彻为图片的轮播

//2.1创设贰个UIImageView增多到Label上

UIImageView*imgView = [[UIImageViewalloc]init];

[msgLabeladdSubview:imgView];

//2.2增多动漫图片

if(receiver) {

imgView.animationImages=@[[UIImageimageNamed:@"chat_receiver_audio_playing000"],

[UIImageimageNamed:@"chat_receiver_audio_playing001"],

[UIImageimageNamed:@"chat_receiver_audio_playing002"],

[UIImageimageNamed:@"chat_receiver_audio_playing003"]];

imgView.frame=CGRectMake(0,0,30,30);

}else{

imgView.animationImages=@[[UIImageimageNamed:@"chat_sender_audio_playing_000"],

[UIImageimageNamed:@"chat_sender_audio_playing_001"],

[UIImageimageNamed:@"chat_sender_audio_playing_002"],

[UIImageimageNamed:@"chat_sender_audio_playing_003"]];

imgView.frame=CGRectMake(msgLabel.bounds.size.width-30,0,30,30);

}

imgView.animationDuration=1;

[imgViewstartAnimating];

animatingImageView= imgView;

}

@end

5卡塔尔国.//消释bug:当输入多行文字时,再点语音开关,那个时候的textView栏不复苏原来高度,则:

在谈天调节器X名爵ChatViewController中的

//监听语音点击开关

- (IBAction)voiceAction:(id)sender {

// 1.来得录音按键

self.recordBtn.hidden= !self.recordBtn.hidden;

if(self.recordBtn.hidden==NO卡塔尔(英语:State of Qatar) {//录音按键要展现

//InputToolBar的惊人要回去暗中同意(46卡塔尔;

self.inputbarHeightConstant.constant=46;

//隐藏键盘

[self.viewendEditing:YES];

}else{

//当不录音的时候,键盘显示

[self.textViewbecomeFirstResponder];

//恢复生机InputToolBar中度(输入几行文字,点击语音按键,再点会文字开关,textView中度不改变)

[selftextViewDidChange:self.textView];

}

}

23.发送图片展示图片

A.发送图片

1卡塔尔(قطر‎.点击输入框的侧边的+按键,到相册选取图片

拖线到闲谈调控器中监听方法:

- (IBAction)showImgPickerAction:(id)sender {

//展现图片选取的调控器

UIImagePickerController*imgPicker = [[UIImagePickerControlleralloc]init];

//设置源

imgPicker.sourceType=UIImagePickerControllerSourceTypePhotoLibrary;

imgPicker.delegate=self;

[selfpresentViewController:imgPickeranimated:YEScompletion:NULL];

/**客商选中图片的回调(代理方法)*/

-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info{

//1.得到客户选中的图纸

UIImage*selectedImg =info[UIImagePickerControllerOriginalImage];

//2.发送图片

[selfsendImg:selectedImg];

//3.藏匿当前图片接受调节器

[selfdismissViewControllerAnimated:YEScompletion:NULL];

}

}

#pragma mark发送图片

-(void)sendImg:(UIImage*)selectedImg{

//1.构造图片音信体

/*

*率先个参数:原始大小的图样对象1000 * 1000

*第4个参数:缩略图的图形对象120 * 120

*/

//将image转化为data

NSData*imageData =UIImagePNGRepresentation(selectedImg);

EMImageMessageBody*body = [[EMImageMessageBodyalloc]initWithData:imageDatathumbnailData:nil];

NSString*from = [[EMClientsharedClient]currentUsername];

//2.生成image音信对象

EMMessage*imageMessage = [[EMMessagealloc]initWithConversationID:self.buddyfrom:fromto:self.buddybody:bodyext:nil];

imageMessage.chatType=EMChatTypeChat;//设置为单聊新闻

//3.发送新闻

//发送全体类型的音信都用那一个接口,只是音讯类型差异

[[EMClientsharedClient].chatManagersendMessage:imageMessageprogress:^(intprogress) {

}completion:^(EMMessage*message,EMError*error) {

NSLog(@"完结音讯发送%@",error卡塔尔(قطر‎;

}];

// 4.把新闻加多到数据源,然后再刷新表格(发送完音信立即显示)

[self.dataSourcesaddObject:imageMessage];

[self.tableViewreloadData];

// 5.把音信展现在顶上部分(发送完音讯自动滚动到键盘顶端)

[selfscrollToBottom];

}

2卡塔尔(قطر‎.收取方法(把发送文书的办法名改为sendText,由于发布文书件、图片、语音都有那些段代码,因而分红一个艺术)

-(void)sendMessage:(EMMessageBody*)body{

//1.生成Message新闻指标

NSString*from = [[EMClientsharedClient]currentUsername];

EMMessage*message = [[EMMessagealloc]initWithConversationID:self.buddyfrom:fromto:self.buddybody:bodyext:nil];

message.chatType=EMChatTypeChat;//设置为单聊新闻

//音信类型为:

//EMChatTypeChat:设置为单聊消息

// EMChatTypeGroupChat:设置为群聊新闻

//EMChatTypeChatRoom:设置为闲谈室音讯

//2.出殡和安葬新闻

//发送全数项指标消息都用那一个接口,只是音信类型分化

[[EMClientsharedClient].chatManagersendMessage:messageprogress:^(intprogress) {

}completion:^(EMMessage*message,EMError*error) {

NSLog(@"实现音讯发送%@",error卡塔尔(英语:State of Qatar);

}];

// 3.把音信加多到数据源,然后再刷新表格(发送完新闻马上展现)

[self.dataSourcesaddObject:message];

[self.tableViewreloadData];

// 4.把信息呈现在最上端(发送完新闻自动滚动到键盘最上端)

[selfscrollToBottom];

}

B.呈现图片

拖入SDWebImage框架,导入#import"UIImageView+WebCache.h"

在ChatCell。M文件中-(void)setMessage:(EMMessage*卡塔尔(英语:State of Qatar)message的章程中

添加elseif([bodyisKindOfClass:[EMImageMessageBodyclass]]卡塔尔(قطر‎{//图片音信

[selfshowImage]; }

-(void)showImage{

//获取图片消息体

EMImageMessageBody*imgBody = (EMImageMessageBody*)self.message.body;

CGRectthumbnailFrm = (CGRect){0,0,imgBody.thumbnailSize};

//设置Label的尺寸丰富展现UIImageView

NSTextAttachment*imgAttach = [[NSTextAttachmentalloc]init];

imgAttach.bounds= thumbnailFrm;

NSAttributedString*imgAtt = [NSAttributedStringattributedStringWithAttachment:imgAttach];

self.chatLabel.attributedText= imgAtt;

//1.cell里增添一个UIImageView

[self.messageLabel addSubview:self.chatImgView];

//2.设置图片控件为缩略图的尺码

self.chatImgView.frame= thumbnailFrm;

//3.下载图片

NSLog(@"thumbnailLocalPath %@",imgBody.thumbnailLocalPath);

NSLog(@"thumbnailRemotePath %@",imgBody.thumbnailRemotePath);

NSFileManager*manager = [NSFileManagerdefaultManager];

//借使当地图片存在,直接从本土显示图片

UIImage*palceImg = [UIImageimageNamed:@"downloading"];

if([managerfileExistsAtPath:imgBody.thumbnailLocalPath]) {

#warning当地路线使用fileURubiconLWithPath方法,网络路线使用U库罗德LWithString:

[self.chatImgViewsd_setImageWithURL:[NSURLfileURLWithPath:imgBody.thumbnailLocalPath]placeholderImage:palceImg];

}else{

//假若地方图片不存,从互连网加载图片

[self.chatImgViewsd_setImageWithURL:[NSURLURLWithString:imgBody.thumbnailRemotePath]placeholderImage:palceImg];

}

}

C.修改bug

1卡塔尔(قطر‎.图片cell会重用,重用的时候理应讲图片移除;在XMGChatCell中增加

增多属性

/**闲谈图片控件*/

@property(nonatomic,strong)UIImageView*chatImgView;

-(UIImageView*)chatImgView{

if(!_chatImgView) {

_chatImgView= [[UIImageViewalloc]init];

}

return_chatImgView;

}

-(void)setMessage:(EMMessage *)message{

//重用时,把闲聊图片控件移除

[self.chatImgView removeFromSuperview];

滑动闲聊调控器时不能在播放语音:

在奥迪(Audi卡塔尔国oPlayTool中增加方法

+(void)stop;

+(void)stop{

//停播语音

[[EMCDDeviceManagersharedInstance]stopPlaying];

//移除动漫

[animatingImageViewstopAnimating];

[animatingImageViewremoveFromSuperview];

}

在闲谈调节器中调用:

-(void)scrollViewWillBeginDragging:(UIScrollView*)scrollView{

//结束语音播放

[AudioPlayToolstop];

}

24.显示时间的cell

岁月显示的国有国法

同样分中内的音信,只彰显叁个时日

/*

15:52

msg1 15:52:10

msg2 15:52:08

msg2 15:52:02

*/

/*今天:时:分(HH:mm)

*昨天:昨天+时+分(昨天HH:mm)

*明日早先:(明天卡塔尔国年:月:日时分(2016-09-26 15:27)

*/

在mainstoryboard中的闲聊调整器中拖三个时刻cell,拖叁个label自动构造,自定义cell(TimeCell)为此类,并将label拖线为属性。设置重用标记。

浅析:数据源数组中不止有模型对象,也一时光字符串对象,因而,在数据源完毕cell方法中,导入TimeCell头文件增多

//推断数据源类型

if([self.dataSources[indexPath.row]isKindOfClass:[NSStringclass]]){//展现时间cell

XMGTimeCell*timeCell = [tableViewdequeueReusableCellWithIdentifier:@"TimeCell"];

timeCell.timeLabel.text=self.dataSources[indexPath.row];

returntimeCell;

}

在cell中度数据源方法中装置时间cell的惊人

//时间cell的冲天是定位

if([self.dataSources[indexPath.row]isKindOfClass:[NSStringclass]]) {

return18;

}

25.显得时间的乘除

新建二个年华测算工具类,世襲自nsobject(观念牛逼)

#import

@interfaceTimeTool : NSObject

//时间戳

+(NSString *)timeStr:(longlong)timestamp;

@end

#import"TimeTool.h"

@implementationTimeTool

+(NSString *)timeStr:(longlong)timestamp{

//重回时间格式

//currentDate 2015-09-28 16:28:09 +0000

//msgDate 2015-09-28 10:36:22 +0000

NSCalendar*calendar =[NSCalendar currentCalendar];

//1.取安妥前的年月

NSDate *currentDate = [NSDate date];

//获取年,月,日

NSDateComponents *components = [calendarcomponents:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:currentDate];

NSInteger currentYear = components.year;

NSInteger currentMonth = components.month;

NSInteger currentDay = components.day;

NSLog(@"currentYear

%ld",components.year);

NSLog(@"currentMonth

%ld",components.month);

NSLog(@"currentDay

%ld",components.day);

//2.赢得音讯发送时间

NSDate *msgDate = [NSDate dateWithTimeIntervalSince1970:timestamp/1000.0];

//获取年,月,日

components = [calendarcomponents:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDayfromDate:msgDate];

CGFloat msgYead = components.year;

CGFloat msgMonth = components.month;

CGFloat msgDay = components.day;

NSLog(@"msgYear

%ld",components.year);

NSLog(@"msgMonth

%ld",components.month);

NSLog(@"msgDay

%ld",components.day);

//3.判断:

/*今天:(HH:mm)

*昨天: (昨天HH:mm)

*明日在此之前:(2014-09-26 15:27)

*/

NSDateFormatter *dateFmt = [[NSDateFormatter alloc] init];

if(currentYear == msgYead

&& currentMonth == msgMonth

&& currentDay == msgDay) {//今天

dateFmt.dateFormat=@"HH:mm";

}elseif(currentYear == msgYead

&& currentMonth == msgMonth

&& currentDay -1== msgDay){//昨天

dateFmt.dateFormat=@"昨天HH:mm";

}else{//几天前早前

dateFmt.dateFormat=@"yyy-MM-dd

HH:mm";

}

return[dateFmt stringFromDate:msgDate];

}

@end

是因为datasource数组须求看清哪些日子增进模型,什么时间增短时间字符串由此写八个独立的不二等秘书籍:在闲聊调整器中期维校正

/**方今增进的时日*/

@property(nonatomic,copy)NSString*currentTimeStr;

-(void)addDataSourcesWithMessage:(EMMessage*)msg{

// 1.推断EMMessage对象前边是或不是要加"时间"

//if (self.dataSources.count == 0) {

////long long timestamp = ([[NSDate date] timeIntervalSince1970] - 60 * 60 *24 * 2) * 1000;

//

//}

NSString*timeStr = [XMGTimeTooltimeStr:msg.timestamp];

if(![self.currentTimeStrisEqualToString:timeStr]) {

[self.dataSourcesaddObject:timeStr];

self.currentTimeStr= timeStr;

}

// 2.再加EMMessage

[self.dataSourcesaddObject:msg];

}

校勘加载数据方式:

-(void)loadLocalChatRecords{

//要是在数组的首先地方增添时间

//[self.dataSources addObject:@"16:06"];

//要取得本地闲谈记录使用会话对象

EMConversation*conversation = [[EaseMobsharedInstance].chatManagerconversationForChatter:self.buddy.usernameconversationType:eConversationTypeChat];

//加载与当前闲谈顾客全部闲聊记录

NSArray*messages = [conversationloadAllMessages];

//for (id obj in messages) {

//NSLog(@"%@",[obj class]);

//}

//增添到数据源

//[self.dataSources addObjectsFromArray:messages];

for(EMMessage*msgObjinmessages) {

[selfaddDataSourcesWithMessage:msgObj];

}

}

改良闲谈调控器中添扩充少源数组方法:

-(void)sendMessage:(id)body{

[selfaddDataSourcesWithMessage:msgObj];

-(void)didReceiveMessage:(EMMessage*)message{

//1.把摄取的音讯加多到数据源

//[self.dataSources addObject:message];

[selfaddDataSourcesWithMessage:message];

27.出示历史会话记录(就是彰显给哪个人聊过天)

在对话调控器XMGConversationViewController中

/**野史会话记录*/

@property(nonatomic,strong)NSArray*conversations;

viewDidLoad添加:

//增多闲谈管理者代理

[[EMClientsharedClient].chatManageraddDelegate:selfdelegateQueue:nil];

//获取历史会话记录

[selfloadConversations];

-(void)loadConversations{

//获取历史会话记录

//1.从内部存储器中获取历史回复记录,获取内部存款和储蓄器中全心得话

//获取具有会话,假如内部存储器中不设有会从DB中加载

NSArray*conversations = [[EMClientsharedClient].chatManagergetAllConversations];

NSLog(@"zzzzzzz %@",conversations);

self.conversations= conversations;

//展现总的未读数

[selfshowTabBarBadge];

}

-(void)showTabBarBadge{

//遍历全数的对话记录,将未读取的新闻数进行累

NSIntegertotalUnreadCount =0;

for(EMConversation*conversationinself.conversations) {

totalUnreadCount += [conversationunreadMessagesCount];

}

self.navigationController.tabBarItem.badgeValue= [NSStringstringWithFormat:@"%ld",totalUnreadCount];

}

在mainstoryboard中找到会话调控器,设置cell的录取标志,cell的style为subtitle

在对话调控器中落实数据源方法

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section {

returnself.conversations.count;

}

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

staticNSString*ID =@"ConversationCell";

UITableViewCell*cell = [tableViewdequeueReusableCellWithIdentifier:ID];

//获取会话模型

EMConversation*conversaion =self.conversations[indexPath.row];

//突显数据

// 1.显得顾客名

cell.textLabel.text= [NSStringstringWithFormat:@"%@ ====未读新闻数:%zd",conversaion.conversationId,conversaion.unreadMessagesCount];

// 2.来得最新的一条记下

//获取新闻体

idbody = conversaion.latestMessage.body;

if([bodyisKindOfClass:[EMTextMessageBodyclass]]) {

EMTextMessageBody*textBody = body;

cell.detailTextLabel.text= textBody.text;

}elseif([bodyisKindOfClass:[EMVoiceMessageBodyclass]]){

EMVoiceMessageBody*voiceBody = body;

cell.detailTextLabel.text= [voiceBodydisplayName];

}elseif([bodyisKindOfClass:[EMImageMessageBodyclass]]){

EMImageMessageBody*imgBody = body;

cell.detailTextLabel.text= imgBody.displayName;

}else{

cell.detailTextLabel.text=@"未知音讯类型";

}

returncell;

}

落到实处部分代理方法:

#pragma mark - EMChatManagerDelegate

//会话列表产生变化调用

- (void)conversationListDidUpdate:(NSArray*)aConversationList{

//给数据源重新赋值

self.conversations= aConversationList;

//刷新表格

[self.tableViewreloadData];

//彰显总的未读数

[selfshowTabBarBadge];

}

//收到音讯

//生机勃勃旦接收到音讯,刷新未读新闻列表

-(void)messagesDidReceive:(NSArray*)aMessages{

//更新表格

[self.tableViewreloadData];

//展现总的未读数

[selfshowTabBarBadge];

}

27.设置音信为已读

点击会话分界面包车型客车cell,会跳到谈天调控器

导入聊天控制器头文件

在mainstoryboard中闲谈调节器中安装storyboardIDChatPage

-(void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath{

//步入到闲聊调节器

//1.从storybaord加载闲聊调控器

ChatViewController*chatVc = [[UIStoryboardstoryboardWithName:@"Main"bundle:nil]instantiateViewControllerWithIdentifier:@"ChatPage"];

//会话

EMConversation*conversation =self.conversations[indexPath.row];

//2.装置好友属性

chatVc.buddy= conversation.conversationId;

//3.突显闲谈分界面

[self.navigationControllerpushViewController:chatVcanimated:YES];

}

到谈心调节器中设置音讯为已读

加上贰个天性

/**时下对话对象*/

@property(nonatomic,strong)EMConversation*conversation;

-(void)loadLocalChatRecords{

self.conversation= conversation;

-(void)addDataSourcesWithMessage:(EMMessage*)msg{

// 3.设置消息为已读取

//将消息设置为已读

//aMessageId要安装音讯的ID

//pError错误音信

[self.conversationmarkMessageAsReadWithId:msg.messageIderror:nil];

上一篇:timeout解决办法,configured错误解决 下一篇:没有了
返回顶部