环信1


1.集成环信sdk


什么是环信


环信是一个第三平台,提供即时通信(IM –Instant Messaging )的服务

环信是在XMPP的基础上进行二次开发

环信在网络上传输的数据也是XML

使用环信,不用自己搭建服务器,节约成本

环信日活30万以下,永远免费  http://www.easemob.com/price

2015年易观发布中国移动IM云报告,环信稳居市场第一

公司如要开发即时通讯软件,建议首选环信,环信占用市场份额较大


其它:


融云  http://www.rongcloud.cn


亲加  http://www.gotye.com.cn


集成环信的前提准备


注册成为环信开发者

http://www.easemob.com



 点击 创建应用 liugang173#lamcochat


应用名称:  lamcochat

产品名称:  lamcochat

注册模式:   选择默认 开发注册 用户可以自己注册    如果选择 授权注册 用户不能自己注册

应用描述:   一个神奇的APP


在开发者后台创建APP获取Key


找到如  应用标识(AppKey): lamco-wangyun#lamcochat   #前是 用户名  后是应用名称


点击 快速集成  下面的 iOS 链接


点击  左侧   iOS客户端集成


点击  右侧   集成IOS SDK前的准备工作



制作并上传推送证书   不需要


点击  左侧  集成IOS SDK


下载SDK

http://www.easemob.com/downloads




1. 从官网上下载下来的包中分为如下四部分:


环信 iOS SDK 开发使用

环信 iOS release note 更新说明

环信 iOS UIDemo 工程源码

环信 iOS UIDemo.ipa 打包的ipa



解压 iOSSDK-20160202.zip   运行 ChatDemo-UI2.0/ChatDemo-UI2.0.xcodeproj  示例   首先需要注册一个账号


参看 课件截图


lamco

123456


点击  Register  在点击  Login


切换到 Setting  点击  log out(lamco)


在注册一个账号


lamco2

123456


点击  Register  在点击  Login


切换到 AddressBook  点击  右上角 +


输入 lamco  点击 右上角 Search   点击  Add


输入 内容 I'm lamco2  点击 ok


切换到 Setting  点击  log out(lamco2)


重新登录


lamco

123456


切换到 AddressBook  点击 Application  and  notification


点击  Accept


返回


点击  lamco2   进行聊天




2. IOS SDK中有三个子文件夹:includelibresources,请不要擅自修改这些文件夹的任何东西,下面依次介绍这三个子文件夹。


lib 静态库,

包含连个静态库libEaseMobClientSDK.a libEaseMobClientSDKLite.a

libEaseMobClientSDKLite.a不包含实时语音功能(打电话  一般电商APP不需要实时语音功能 .a静态库 文件大小差异也非常大)

libEaseMobClientSDK.a包含所有功能。如果你的app中不需要实时语音功能,删掉libEaseMobClientSDK.a只使用libEaseMobClientSDKLite.a即可。


工程中只能21  不能2个同时添加


resources sdkbundle

包含旧版sdk的数据库(.momd 使用coredata实现 现在使用 SQLite)、消息提示音,sdk配置文件。其中sdk配置文件已加密,旧版sdk数据库几乎没什么实质作用。


右键   EaseMob.bundle  显示包内容   .momd文件 是使用coredata实现


include 包含sdk的头文件。



3. 主要介绍下include,所有的接口都在这个文件夹中。


EaseMobClientSDK/EaseMobClientSDKLite 包含在项目中要引用的总头文件,即在代码中只需#import”EMSDKFull.h”#import”EaseMob.h”即可调用所有对应的api

CallService 包含实时语音相关的接口

ChatService 包含聊天相关的接口,比如注册、登录、退出、单聊、群聊、群组等

Utility 包含DeviceManagerErrorManagerDeviceManager硬件相关接口,ErrorManager错误码定义

具体接口讲解请转到Apple Docs


注:


include包含5个子文件夹:CallServiceChatServiceEaseMobClientSDKEaseMobClientSDKLiteUtility

类似EM@Manager命名格式的文件夹的内部结构都是相似的。delegates文件夹包含各种代理接口,internal文件夹包含各种协议的声明,types文件夹包含各种实例的声明。




new  project  ...  single  view  application  name:lamcoChat


右键 lamcoChat 目录  new group name:Lib


iOSSDK-20160202/EaseMobSDK  添加到Lib 目录下


展开  EaseMobSDK/lib      libEaseMobClientSDK.a  libEaseMobClientSDKLite.a 只能21  不能2个同时添加


删除 libEaseMobClientSDKLite.a


在删除对应的 EaseMobSDK/include/EaseMobClientSDKLite 目录





右键 lamcoChat 工程 new group name:Dependences



添加依赖库


CFNetwork.framework


MobileCoreServices.framework


libresolv.dylib


libz.dylib


libiconv.dylib


libxml2.dylib


libsqlite3.dylib


libstdc++.6.0.9.dylib


如果使用的是xcode7,后缀为tbd


将以上的库文件拖拽到  Dependences  目录中



选中 lamcoChat 工程  切换到 Build Settings 点击 All   搜索  Other Linker Flags    添加-ObjC(注意大小写)


说明:如果项目中使用-ObjC有冲突,可以添加-force_load来解决

因为没有使用 libEaseMobClientSDKLite.a 文件 所以无需配置


以上步骤进行完后,编译工程,如果没有报错,恭喜你,集成sdk成功,可以进行下一步了。



以上步骤可以参考文档  http://docs.easemob.com/doku.php?id=start:300iosclientintegration:20iossdkimport



集成SDK基础功能


参考文档  http://docs.easemob.com/doku.php?id=start:300iosclientintegration:30iossdkbasic




2.登录



打开  AppDelegate.m


加入  #import "EaseMob.h"


删除类中所有方法  在加入方法


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

{

    NSLog(@"%@",NSHomeDirectory());

    

    //registerSDKWithAppKey:注册的appKey,详细见下面注释。

    //apnsCertName:推送证书名(不需要加后缀),详细见下面注释。

    //    [[EaseMob sharedInstance] registerSDKWithAppKey:@"lamco-wangyun#lamcochat" apnsCertName:nil];

    // 1.初始化SDK,并隐藏环信SDK的日志输入

    [[EaseMob sharedInstance] registerSDKWithAppKey:@"lamco-wangyun#lamcochat" apnsCertName:nil otherConfig:@{kSDKConfigEnableConsoleLogger:@(NO)}];

    [[EaseMob sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];

    

    

    return YES;

}


// App进入后台

- (void)applicationDidEnterBackground:(UIApplication *)application

{

    [[EaseMob sharedInstance] applicationDidEnterBackground:application];

}


// App将要从后台返回

- (void)applicationWillEnterForeground:(UIApplication *)application

{

    [[EaseMob sharedInstance] applicationWillEnterForeground:application];

}


// 申请处理时间

- (void)applicationWillTerminate:(UIApplication *)application

{

    [[EaseMob sharedInstance] applicationWillTerminate:application];

}




登录:调用SDK的登录接口进行的操作; 提供了三种方法。


1. 同步方法:


EMError *error = nil;

NSDictionary *loginInfo = [[EaseMob sharedInstance].chatManager loginWithUsername:@"8001" password:@"111111" error:&error];

if (!error && loginInfo) {

    NSLog(@"登陆成功");

}

2. block异步方法


[[EaseMob sharedInstance].chatManager asyncLoginWithUsername:@"8001" password:@"111111" completion:^(NSDictionary *loginInfo, EMError *error) {

    if (!error && loginInfo) {

        NSLog(@"登陆成功");

    }

} onQueue:nil];

3. IChatManagerDelegate回调方法


接口调用


[[EaseMob sharedInstance].chatManager asyncLoginWithUsername:@"8001" password:@"111111"];




右键 lamcoChat new group name:Login


右键  Login    new  class  ...  name:XMGLoginViewController

superclass:UIViewController


打开  XMGLoginViewController.m


加入  #import "EaseMob.h"


在延展中加入


@property (weak, nonatomic) IBOutlet UITextField *usernameField;


@property (weak, nonatomic) IBOutlet UITextField *passwordField;



在类中加入方法


- (IBAction)registerAction:(id)sender {

    

    

}


- (IBAction)loginAction:(id)sender {

    

    NSString *username = self.usernameField.text;

    NSString *password = self.passwordField.text;

    

    if (username.length == 0 || password.length == 0) {

        NSLog(@"请输入账号和密码");

        return;

    }

    

    

    // 登录

    [[EaseMob sharedInstance].chatManager asyncLoginWithUsername:username password:password completion:^(NSDictionary *loginInfo, EMError *error) {

        // 登录请求完成后的block回调

        if (!error) {

            /*  字典loginInfo返回的数据

             {

             LastLoginTime = 1443083631296;

             jid = "vgios#xmg1chat_xmgtest1@easemob.com";

             password = 123456;

             resource = mobile;

             token = "YWMt-2kmTmKWEeWhivny1t_c6gAAAVEzekiFP9xOO0dqxYGGu4uI5CZNNCoaV0Y";

             username = xmgtest1;

             }

             */

            NSLog(@"登录成功 %@",loginInfo);

            

            // 来主界面

            self.view.window.rootViewController = [UIStoryboard storyboardWithName:@"Main" bundle:nil].instantiateInitialViewController;

            

        }else{

            NSLog(@"登录失败 %@",error);

            //User do not exist.

            /** 每一个应用都有自己的注册用户*/

        }

        

        

        

    } onQueue:dispatch_get_main_queue()];

}






右键 lamcoChat new group name:Xib


Main.storyboard  LaunchScreen.xib 拖拽到 该目录下


右键  Xib  new  file  ...  User Interface  Storyboard name:  Login.storyboard



打开  Login.storyboard


在面板中添加  ViewController


  ViewController  变为   NavigationController



双击 ViewController  顶部的 Navigation Bar   设置 title:Lamco


设置 ViewController  class:XMGLoginViewController


view 中添加 textfield   text:lamco

Placeholder:请输入账号

x   y   width  height:37 91  228  30


view 中添加 textfield   text:123456

Placeholder:请输入密码

x   y   width  height:37 136  228  30


view 中添加 button   text:Register


x   y   width  height:76 202  57  30


view 中添加 button   text:Login


x   y   width  height:204 202  38  30



连接输出口与事件



选中 Navigation Controller   勾选 Is Initial View Controller


选中 工程 设置  Main Interface :Login



每一个应用都有自己的注册用户



回到  https://console.easemob.com/app_info.html


点击 IM用户


点击  注册IM用户



用户名:lamco

密码:123456

确认密码:123456



运行   点击 登录  查看 控制台 如返回数据



登录成功 {

    LastLoginTime = 1455789814586;

    jid = "lamco-wangyun#lamcochat_lamco@easemob.com";

    password = 123456;

    resource = mobile;

    token = YWMt3xjDnNYmEeWIazMWMiAmAwAAAVQo00LH24qzWhoyhs0gAcfnCE9K4ZvOh08;

    username = lamco;

}




3.注册


注册模式分两种,开放注册和授权注册。只有开放注册时,才可以客户端注册。


开放注册是为了测试使用,正式环境中不推荐使用该方式注册环信账号, 授权注册的流程应该是您服务器通过环信提供的rest api注册,之后保存到您的服务器或返回给客户端。


注册提供了三种方法。


1. 同步方法


EMError *error = nil;

BOOL isSuccess = [[EaseMob sharedInstance].chatManager registerNewAccount:@"8001" password:@"111111" error:&error];

if (isSuccess) {

    NSLog(@"注册成功");

}



2. block异步方法


[[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:@"8001" password:@"111111" withCompletion:^(NSString *username, NSString *password, EMError *error) {

    if (!error) {

        NSLog(@"注册成功");

    }

} onQueue:nil];



3. IChatManagerDelegate回调方法


接口调用


[[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:@"8001" password:@"111111"];

监听回调方法


/*!

 @method

 @brief 注册新用户后的回调

 @discussion

 @result

 */

- (void)didRegisterNewAccount:(NSString *)username

password:(NSString *)password

error:(EMError *)error;



打开 XMGLoginViewController.m


修改  registerAction  方法如下


- (IBAction)registerAction:(id)sender {

    NSString *username = self.usernameField.text;

    NSString *password = self.passwordField.text;

    

    if (username.length == 0 || password.length == 0) {

        NSLog(@"请输入账号和密码");

        return;

    }

    

    

    // 注册

    [[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:username password:password withCompletion:^(NSString *username, NSString *password, EMError *error) {

        NSLog(@"%@",[NSThread currentThread]);

        if (!error) {

            NSLog(@"注册成功");

        }else{

            NSLog(@"注册失败 %@",error);

        }

        

    } onQueue:nil];

    

}



运行


点击  Register


查看 控制台   注册失败 Username already exists.


输入 lamco2

123456


查看 控制台     注册成功



刷新  https://console.easemob.com/app_users.html   查看是否注册成功




4.自动登录


自动登录:当然程序再次启动时,如果用户已经成功登录过,不需要用户再输入用户名和密码进行登录


实现方法

把登录帐号信息保存下来,程序起动发送登录请求

环信已经实现了自动登录,只需要在第一次登录成功后调用 下面的方法即可[[EaseMob sharedInstance].chatManager setIsAutoLoginEnabled:YES];


总结:不管哪种方法,实质都是再次调用了登录的网络请求



loginAction  方法中的


NSLog(@"登录成功 %@",loginInfo);


下面加入


// 设置自动登录

[[EaseMob sharedInstance].chatManager setIsAutoLoginEnabled:YES];


运行    点击 登录


进入到沙盒路径


/Users/koukou/Library/Developer/CoreSimulator/Devices/F88FD5FE-98DB-4409-828E-EB7351CE2B6E/data/Containers/Data/Application/BC83439C-8B18-4A4C-A6DC-D85F902F39F3


找到 easemobDB  下面的   easemobConfig.plist  里面存储账号、密码信息





监听自动登录


打开  AppDelegate.m


didFinishLaunchingWithOptions  方法中的


[[EaseMob sharedInstance] application:application didFinishLaunchingWithOptions:launchOptions];

下面加入


// 2.监听自动登录的状态

// 设置chatManager代理

// 写个nil 默认代理会在主线程调用

[[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:nil];


// 3.如果登录过,直接来到主界面

if ([[EaseMob sharedInstance].chatManager isAutoLoginEnabled]) {

    self.window.rootViewController = [UIStoryboard storyboardWithName:@"Main" bundle:nil].instantiateInitialViewController;

}



在类中加入方法


#pragma mark 自动登录的回调

-(void)didAutoLoginWithInfo:(NSDictionary *)loginInfo error:(EMError *)error{

    if (!error) {

        NSLog(@"自动登录成功 %@",loginInfo);

    }else{

        NSLog(@"自动登录失败 %@",error);

    }

    

}



运行



5.自动连接功能


如果网络不通过,用户应该自动连接到服务器,以及时接收消息

此功能无需程序员自己做,环信框架已实现,环信SDK会调用自动连接的代理方法来通知应用程序



右键   lamcoChat  --- new group  name:Conversation【会话】


右键  Conversation【会话】    new class  name:XMGConversationViewController

superclass:UITableViewController



打开   XMGConversationViewController.m


加入  #import "EaseMob.h"


在延展中加入   <EMChatManagerDelegate>


viewDidLoad  方法中加入


//设置代理

[[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:nil];



在类中加入方法


#pragma mark - chatManager代理方法

//1.监听网络状态

- (void)didConnectionStateChanged:(EMConnectionState)connectionState{

    //    eEMConnectionConnected,   //连接成功

    //    eEMConnectionDisconnected,//未连接

    if (connectionState == eEMConnectionDisconnected) {

        NSLog(@"网络断开,未连接...");

        self.title = @"未连接.";

    }else{

        NSLog(@"网络通了...");

    }

    

}



-(void)willAutoReconnect{

    NSLog(@"将自动重连接...");

    self.title = @"连接中....";

}


-(void)didAutoReconnectFinishedWithError:(NSError *)error{

    if (!error) {

        NSLog(@"自动重连接成功...");

        self.title = @"Conversation";

    }else{

        NSLog(@"自动重连接失败... %@",error);

    }

}







打开 Main.storyboard


删除 ViewController


添加 tabarController


2 ViewController 删除


面板中 添加3   NavigationController


分别连接到 tabarController


设置3 item title分别为 ConversationAddressBookSettings



设置  Conversation   右侧对应的 class:XMGConversationViewController



选中 tabarController   勾选 Is Initial View Controller



运行

断开网络  查看控制台与 控制器title


网络断开,未连接...


连接网络  查看控制台   控制器title


网络通了...




也可以使用真机  切换到 飞行模式/取消飞行模式 测试功能




环信总结:


使用环信的思想


》所有网络请求使用 [EaseMob sharedInstance].chatManager "聊天管理器"

》结果(自动登录、自动连接)-通过代理来回调

调用chatManager "聊天管理器" - (void)addDelegate:(id<EMChatManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)queue;







6.添加好友请求


右键  lamcoChat   --- new  group  name:AddressBook【通讯录】


右键  AddressBook【通讯录】   ---  new  class  name:XMGAddFriendViewController

superclass:UIViewController


打开  XMGAddFriendViewController.m


加入  #import "EaseMob.h"


在延展中加入


<EMChatManagerDelegate>

@property (weak, nonatomic) IBOutlet UITextField *textField;



在类中加入方法


- (IBAction)addFriendAction:(id)sender {

    

    // 添加好友

    

    // 1.获取要添加好友的名字

    NSString *username = self.textField.text;

    

    

    // 2.向服务器发送一个添加好友的请求

    // buddy 哥儿们

    // message 请求添加好友的 额外信息

    NSString *loginUsername = [[EaseMob sharedInstance].chatManager loginInfo][@"username"];

    NSString *message = [@"我是" stringByAppendingString:loginUsername];

    

    EMError *error =  nil;

    [[EaseMob sharedInstance].chatManager addBuddy:username message:message error:&error];

    if (error) {

        NSLog(@"添加好友有问题 %@",error);

        

    }else{

        NSLog(@"添加好友没有问题");

    }

    

}




打开  Main.storyboard


在第二个 tableView 导航栏右侧 bar button  item  设置 System Item :Add


在第二个 tableView 右侧 添加一个 ViewController


设置 class:XMGAddFriendViewController


Add  连接到   XMGAddFriendViewController  选择  show


设置  XMGAddFriendViewController  Navigation Bar  title:Add Firend


  view  中添加  textfield    Placeholder:请输入要添加好友的名称

x  y  width  height:32 91  241  91


  view  中添加  button    text:Add Firend

x  y  width  height:123  142  75  30


连接输出口与事件


运行  切换到 AddressBook  点击输入 lamco2


查看控制台  添加好友没有问题





打开 iOSSDK-20160202/ChatDemo-UI2.0/ChatDemo-UI2.0.xcodeproj  示例



打开  AppDelegate+EaseMob.m


45 中的  easemob-demo#chatdemoui


改为   lamco-wangyun#lamcochat



运行


lamco2

123456



点击  AddressBook   Application and  notification  点击  Accept



打开  XMGAddFriendViewController.m


viewDidLoad 方法中加入


// 添加(聊天管理器)代理

[[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:nil];



在类中加入方法



#pragma mark - 好友添加的代理方法

#pragma mark 好友请求被同意

-(void)didAcceptedByBuddy:(NSString *)username{

    

    // 提醒用户,好友请求被同意

    NSString *message = [NSString stringWithFormat:@"%@ 同意了你的好友请求",username];

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"好友添加消息" message:message delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil];

    [alert show];

}


#pragma mark 好友请求被拒绝

-(void)didRejectedByBuddy:(NSString *)username{

    // 提醒用户,好友请求被同意

    NSString *message = [NSString stringWithFormat:@"%@ 拒绝了你的好友请求",username];

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"好友添加消息" message:message delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil];

    [alert show];

    

}



- (void)dealloc

{

    //移除聊天管理器的代理

    [[EaseMob sharedInstance].chatManager removeDelegate:self];

}



运行

添加好友   lamco2



切换到app    EaseMobDB   点击Accept


切换到app  lamcoChat   弹出窗口



运行

添加好友   lamco2



切换到app    EaseMob   点击Reject


切换到app  lamcoChat   弹出窗口



打开  XMGAddFriendViewController.m


  viewDidLoad  方法中的


[[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:nil];


注释掉



将方法 didAcceptedByBuddydidRejectedByBuddydealloc



剪切到 XMGConversationViewController.m 文件中


即通过  ConversationViewController  统一管理



总结:


添加好友注意

1.添加聊天管理器的代理时,在控制器被dealloc的时候,应该移除代理

2.添加好友的代理方法,最好放在Conversation的控制器实现





7.显示好友列表数据


查看沙盒 下面的Library/easemobDB/lamco.db  打开后找到表 Buddy


打开  XMGLoginViewController.m


loginAction  方法第一句位置加入


// 让环信SDK"第一次"登录完成之后,自动从服务器获取好友列表,添加到本地数据库(Buddy)

[[EaseMob sharedInstance].chatManager setIsAutoFetchBuddyList:YES];



右键  AddressBook【通讯录】  --- new  class  name:XMGAddressBookViewController

superclass:UITableViewController


打开  XMGAddressBookViewController.m


修改代码如下


//

//  XMGAddressBookViewController.m

//  xmg1chat

//


#import "XMGAddressBookViewController.h"

#import "EaseMob.h"


@interface XMGAddressBookViewController ()<EMChatManagerDelegate>


/** 好友列表数据源 */

@property (nonatomic, strong) NSArray *buddyList;


@end


@implementation XMGAddressBookViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    

    // 添加聊天管理器的代理

    [[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:nil];

    

    // 获取好友列表数据

    /* 注意

     * 1.好友列表buddyList需要在自动登录成功后才有值

     * 2.buddyList的数据是从 本地数据库获取

     * 3.如果要从服务器获取好友列表 调用chatManger下面的方法

     -(void *)asyncFetchBuddyListWithCompletion:onQueue:;

     * 4.如果当前有添加好友请求,环信的SDK内部会往数据库的buddy表添加好友记录

     * 5.如果程序删除或者用户第一次登录,buddyList表是没记录,

     解决方案

     1》要从服务器获取好友列表记录

     2》用户第一次登录后,自动从服务器获取好友列表

     */

    

    self.buddyList =  [[EaseMob sharedInstance].chatManager buddyList];

    NSLog(@"=== %@",self.buddyList);

    

    //    [[EaseMob sharedInstance].chatManager asyncFetchBuddyListWithCompletion:^(NSArray *buddyList, EMError *error) {

    //        self.buddyList = buddyList;

    //    } onQueue:<#(dispatch_queue_t)#>]

    

#warning 强调buddyList没有值的情况 1.第一次登录 2.自动登录还没有完成

    //    if (self.buddyList.count == 0) {//数据库没有好友记录

    //

    //    }

}



#pragma mark - Table view data source


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

    return self.buddyList.count;

}



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

    

    static NSString *ID = @"BuddyCell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    

    

    // 1。获取好友模型

    EMBuddy *buddy = self.buddyList[indexPath.row];

    

    // 2.显示头像

    cell.imageView.image = [UIImage imageNamed:@"chatListCellHead"];

    

    // 3.显示名称

    cell.textLabel.text = buddy.username;

    

    return cell;

}



#pragma mark - chatmanger的代理

#pragma mark - 监听自动登录成功

-(void)didAutoLoginWithInfo:(NSDictionary *)loginInfo error:(EMError *)error{

    if (!error) {//自动登录成功,此时buddyList就有值

        self.buddyList = [[EaseMob sharedInstance].chatManager buddyList];

        NSLog(@"=== %@",self.buddyList);

        [self.tableView reloadData];

    }

}



@end




打开  Main.storyboard


设置 第二个 TableViewController class:XMGAddressBookViewController


设置 cell  Identifier:BuddyCell



在模拟器中删除  lamcoChat  应用


重新  运行



new file  … Resourse Rich Text File    name:ReadMe


打开 ReadMe.rtf


加入



1.使用环信的思想

》所有网络请求使用 [EaseMob sharedInstance].chatManager "聊天管理器"

》结果(自动登录、自动连接)-通过代理来回调

调用chatManager "聊天管理器" - (void)addDelegate:(id<EMChatManagerDelegate>)delegate delegateQueue:(dispatch_queue_t)queue;


2.添加好友注意

1.添加聊天管理器的代理时,在控制器被dealloc的时候,应该移除代理

2.添加好友的代理方法,最好放在Conversation的控制器实现


3.获取好友列表数据

/* 注意

 * 1.好友列表buddyList需要在自动登录成功后才有值

 * 2.buddyList的数据是从 本地数据库获取

 * 3.如果要从服务器获取好友列表 调用chatManger下面的方法

 -(void *)asyncFetchBuddyListWithCompletion:onQueue:;

 * 4.如果当前有添加好友请求,环信的SDK内部会往数据库的buddy表添加好友记录

 * 5.如果程序删除或者用户第一次登录,buddy表是没记录,

 解决方案

 1》要从服务器获取好友列表记录

 2》设置用户第一次登录后,自动从服务器获取好友列表

 */



4.接收到好友的同意好友请求后,要刷新好友列表数据








8.好友请求同意后刷新通讯录



注册新用户   lamco3

123456



在回到lamcoChat 应用  添加 lamco3


切换到 环信APP  接受


lamcoChat  并没有显示lamco3


重新运行 lamcoChat  后显示 lamco3 好友


因为重启后调用数据库文件获取到lamco3数据





实现  接收到好友的同意好友请求后,要刷新好友列表数据




打开  XMGAddressBookViewController.m


加入方法


#pragma mark 好友添加请求同意

-(void)didAcceptedByBuddy:(NSString *)username{

    // 把新的好友显示到表格

    NSArray *buddyList = [[EaseMob sharedInstance].chatManager buddyList];

    NSLog(@"好友添加请求同意 %@",buddyList);

#warning buddyList的个数,仍然是没有添加好友之前的个数,从新服务器获取

    [self loadBuddyListFromServer];

    

    

}


#pragma mark 从新服务器获取好友列表

-(void)loadBuddyListFromServer{

    [[EaseMob sharedInstance].chatManager asyncFetchBuddyListWithCompletion:^(NSArray *buddyList, EMError *error) {

        NSLog(@"从服务器获取的好友列表 %@",buddyList);

        

        // 赋值数据源

        self.buddyList = buddyList;

        

        // 刷新

        [self.tableView reloadData];

        

    } onQueue:nil];

}


#pragma mark 好友列表数据被更新

-(void)didUpdateBuddyList:(NSArray *)buddyList changedBuddies:(NSArray *)changedBuddies isAdd:(BOOL)isAdd{

    

    NSLog(@"好友列表数据被更新 %@",buddyList);

    // 重新赋值数据源

    self.buddyList = buddyList;

    // 刷新

    [self.tableView reloadData];

}



运行



9.接收好友的请求



打开  XMGConversationViewController.m


修改延展如下


@interface XMGConversationViewController ()<EMChatManagerDelegate,UIAlertViewDelegate>


/** 好友的名称 */

@property (nonatomic, copy) NSString *buddyUsername;


@end




加入方法


#pragma mark 自动登录的回调

-(void)didAutoLoginWithInfo:(NSDictionary *)loginInfo error:(EMError *)error{

    if (!error) {

        NSLog(@"%s 自动登录成功 %@",__FUNCTION__, loginInfo);

    }else{

        NSLog(@"自动登录失败 %@",error);

    }

    

}


#pragma mark 接收好友的添加请求

-(void)didReceiveBuddyRequest:(NSString *)username message:(NSString *)message{

    

    // 赋值

    self.buddyUsername = username;

    

    // 对话框

    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"好友添加请求" message:message delegate:self cancelButtonTitle:@"拒绝" otherButtonTitles:@"同意", nil];

    [alert show];

    

}



-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{

    

    if (buttonIndex == 0) {//拒绝好友请求

        [[EaseMob sharedInstance].chatManager rejectBuddyRequest:self.buddyUsername reason:@"我不认识你" error:nil];

    }else{//同意好友请求

        [[EaseMob sharedInstance].chatManager acceptBuddyRequest:self.buddyUsername error:nil];

        

    }

}


运行



10.删除好友


打开  XMGAddressBookViewController.m


加入方法


#pragma mark  实现下面的方法就会出现表格的Delete按钮

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

    

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        

        // 获取移除好友的名字

        EMBuddy *buddy = self.buddyList[indexPath.row];

        NSString *deleteUsername = buddy.username;

        

        // 删除好友  YES 表示对方好友也看不到自己

        [[EaseMob sharedInstance].chatManager removeBuddy:deleteUsername removeFromRemote:YES error:nil];

    }

    

}



运行



11.监听被好友删除


打开 XMGConversationViewController.m


加入方法


#pragma mark 监听被好友删除

-(void)didRemovedByBuddy:(NSString *)username{

    

    NSString *message = [username stringByAppendingString:@" 把你删除"];

    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"xxxx" message:message delegate:nil cancelButtonTitle:@"知道了" otherButtonTitles:nil, nil];

    [alert show];

    

    

}



打开 XMGAddressBookViewController.m


加入方法


#pragma mark 被好友删除

-(void)didRemovedByBuddy:(NSString *)username{

    

    // 刷新表格  从服务器再次获取最新数据

    [self loadBuddyListFromServer];

    

}



运行



12.退出登录



EMChatManagerBuddyDelegate 协议的实现了对用户的基本操作,如


添加好友

从本地获取好友列表

从服务器获取最新好友列表

接收好友添加请求

删除好友

被好友从名单上删除



右键 lamcoChat   new group  name:Setting


右键  Setting  —  new   class  name:XMGSettingViewController

superclass:UITableViewController


打开 XMGSettingViewController.m


加入 #import "EaseMob.h"


在延展中加入


- (IBAction)logoutAction:(id)sender;

@property (weak, nonatomic) IBOutlet UIButton *logoutBtn;



修改 viewDidLoad  方法如下


- (void)viewDidLoad {

    [super viewDidLoad];

    

    

    // 当前登录的用户名

    NSString *loginUsername = [[EaseMob sharedInstance].chatManager loginInfo][@"username"];

    

    NSString *title = [NSString stringWithFormat:@"log out(%@)",loginUsername];

    

    //1.设置退出按钮的文字

    [self.logoutBtn setTitle:title forState:UIControlStateNormal];

}


在加入方法


- (IBAction)logoutAction:(id)sender {

    //UnbindDeviceToken 不绑定DeviceToken

    // DeviceToken 推送用

    [[EaseMob sharedInstance].chatManager asyncLogoffWithUnbindDeviceToken:YES completion:^(NSDictionary *info, EMError *error) {

        if (error) {

            NSLog(@"退出失败 %@",error);

            

        }else{

            NSLog(@"退出成功");

            // 回到登录界面

            self.view.window.rootViewController = [UIStoryboard storyboardWithName:@"Login" bundle:nil].instantiateInitialViewController;

            

        }

    } onQueue:nil];

}






打开  Main.storyboard


设置第三个 Navigation Controller 右侧  tableViewController  class: XMGSettingViewController


选中 tableView


设置 Content :Static Cells

Style:Grouped


删除2 cell


像剩余的cell 添加 button  设置 background:gray

x   y  width  height: 21  13  278 35


点击 右下角  勾选上下左右   增加约束



设置 Navigation Bar    title:Setting



连接 按钮输出口与事件



运行



13.聊天界面-工具条排版



右键 lamcoChat   new group  name:Chat【聊天】


右键  Chat【聊天】  —  new   class  name:XMGChatViewController

superclass:UIViewController


打开 XMGChatViewController.m


在延展中加入


/**输入工具条底部的约束*/

@property (weak, nonatomic) IBOutlet NSLayoutConstraint *inputToolBarBottomConstraint;



修改  viewDidLoad 方法如下


- (void)viewDidLoad {

    [super viewDidLoad];

    

    //1.监听键盘弹出,把inputToolbar(输入工具条)往上移

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbWillShow:) name:UIKeyboardWillShowNotification object:nil];

    

    //2.监听键盘退出,inputToolbar恢复原位

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(kbWillHide:) name:UIKeyboardWillHideNotification object:nil];

}



在类中加入方法


#pragma mark 键盘显示时会触发的方法

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

    

    //1.获取键盘高度

    //1.1获取键盘结束时候的位置

    CGRect kbEndFrm = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];

    CGFloat kbHeight = kbEndFrm.size.height;

    

    

    //2.更改inputToolbar 底部约束

    self.inputToolBarBottomConstraint.constant = kbHeight;

    //添加动画

    [UIView animateWithDuration:0.25 animations:^{

        [self.view layoutIfNeeded];

    }];

    

    

}

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

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

    //inputToolbar恢复原位

    self.inputToolBarBottomConstraint.constant = 0;

}



-(void)dealloc{

    [[NSNotificationCenter defaultCenter] removeObserver:self];

}



将课件中的 images 添加到  Assets.xcassets 


打开 Main.storyboard


AddressBook  控制器 右侧的TableView 控制器右侧 在添加 ViewController  class: XMGChatViewController



选中  BuddyCell   连接到   XMGChatViewController 控制器上  选择 show


设置 Navigation Bar 中间添加  Navigation Item    title:聊天界面


选中 控制器 XMGChatViewController   Bottom Bar:None

勾选 hide bottom bar  on push


root view 中添加  table view     x   y  width  height: 0  64  320  370

keyboard:Dismiss on drag   拖动时隐藏键盘


连接输出口与 delegatedataSource


http://blog.csdn.net/lg_codemachine/article/details/51601688

root view 中添加  view     x   y  width  height: 0  434  320 46

background:gray


选中新添加的 view  点击 右下角   勾选 左右下   (下选择view)

勾选  height 46


设置  label:ChatInputToolBar



ChatInputToolBar  中添加 button    type:Custom

去掉  title

Image:chatBar_record

x   y   width  height:8 8 30 30

label:voiceBtn


选中新添加的 button  点击 右下角   勾选 左下

勾选  width height



ChatInputToolBar  中添加 button    type:Custom

去掉  title

Image:chatBar_face

x   y   width  height:244 8 30 30

label:faceBtn


选中新添加的 button  点击 右下角   勾选 右下

勾选  width height



ChatInputToolBar  中添加 button    type:Custom

去掉  title

Image:chatBar_more

x   y   width  height:282 8 30 30

label:moreBtn



选中新添加的 button  点击 右下角   勾选 右下

勾选  width height



ChatInputToolBar  中添加 textView

去掉  title

background:purple


x   y   width  height:43  6  196  33

label:moreBtn



选中新添加的 textView  点击 右下角   勾选 上下左右

勾选  width height





连接 ChatInputToolBar 底部约束 ChatInputToolBar.bottom=bottomMargin 的输出口   inputToolBarBottomConstraint






选中 table view   点击 右下角   勾选 上下左右



运行




14.聊天界面-接收方cell的排版


右键  Chat【聊天】 —  new class  name:XMGChatCell

superclass:UITableViewCell


打开  XMGChatCell.h


加入  @property (weak, nonatomic) IBOutlet UILabel *messageLabel;



打开  XMGChatViewController.m


加入  #import "XMGChatCell.h"


在延展中加入  <UITableViewDataSource,UITableViewDelegate>


加入方法


#pragma mark 表格数据源

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

    return 20;

}


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

    return 200;

}


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

    static NSString *ID = @"ReceiverCell";

    

    XMGChatCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

    

    //显示内容

    

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

    

    return cell;

    

    

}





打开  Main.storyboard


XMGChatViewController 控制器中的  table view 中添加  cell


设置 class:XMGChatCell

label:ReceiverCell

Identifier:ReceiverCell

background: Brown

Row  Height:73



Content View  中添加 imageView    image:chatListCellHead

x  y width  height:5  5 35  35


设置  约束    勾选 :5  :5

取消选中  Constrain  to margins

勾选 Width:35  Height:35


Content View  中添加 imageView    image:chat_receiver_bg

label:messageBg

Stretching:    x  y width  height:0.5 0.7 0 0    拉伸图片

x  y width  height:45  5 67  41


Content View  中添加 label       lines:0

Preferred Width:242    预先宽度  宽度不能超过242

x  y width  height:60  15  42  21


连接 messageLabel  输出口


设置  约束    勾选 :15  :20

取消选中  Constrain  to margins


同时选中  chat_receiver_bgmessageLabel


设置约束   点击右下角第一个   勾选 Leading Edges

Trailing Edges

Top Edges

Bottom Edges



找到 约束 Message Label.top     Constrain    10

找到 约束 Message Label.bottom  Constrain    -10

找到 约束 Message Label.leading Constrain    15

找到 约束 Message Label.trailing Constrain    -10




运行



15.聊天界面-发送方cell的排版



打开 XMGChatCell.h


修改代码如下


#import <UIKit/UIKit.h>

static NSString *ReceiverCell = @"ReceiverCell";

static NSString *SenderCell = @"SenderCell";

@interface XMGChatCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UILabel *messageLabel;



-(CGFloat)cellHeghit;


@end



打开  XMGChatCell.m


加入方法



/** 返回cell的高度*/

-(CGFloat)cellHeghit{

    //1.重新布局子控件

    [self layoutIfNeeded];

    

    return 5 + 10 + self.messageLabel.bounds.size.height + 10 + 5;

    

}



打开  XMGChatViewController.m


在延展中加入


/** 数据源 */

@property (nonatomic, strong) NSMutableArray *dataSources;


@property (weak, nonatomic) IBOutlet UITableView *tableView;


/** 计算高度的cell工具对象 */

@property (nonatomic, strong) XMGChatCell *chatCellTool;




加入方法



-(NSMutableArray *)dataSources{

    if (!_dataSources) {

        _dataSources = [NSMutableArray array];

    }

    

    return _dataSources;

}


  viewDidLoad  方法中的


[super viewDidLoad];


下面加入


//初始化数据

[self.dataSources addObject:@"xcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfa"];

[self.dataSources addObject:@"xcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafa"];

[self.dataSources addObject:@"xcsafasdfxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfasadfa"];

[self.dataSources addObject:@"xcsafaxcsafasdfsadfasdfsadfa"];

[self.dataSources addObject:@"xcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfa"];

[self.dataSources addObject:@"xcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafa"];

[self.dataSources addObject:@"xcsafasdfxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfasadfa"];

[self.dataSources addObject:@"xcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafa"];


[self.dataSources addObject:@"xcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfa"];

[self.dataSources addObject:@"xcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafaxcsafasdfsadxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfafa"];

[self.dataSources addObject:@"xcsafasdfxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfasadfa"];

[self.dataSources addObject:@"xcsafaxcsafasdfsadfasdfsadfa"];



// 给计算高度的cell工具对象 赋值

self.chatCellTool = [self.tableView dequeueReusableCellWithIdentifier:ReceiverCell];



修改 numberOfRowsInSectionheightForRowAtIndexPathcellForRowAtIndexPath  3个方法如下


#pragma mark 表格数据源

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

    return self.dataSources.count;

}


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

    // 设置label的数据

#warning 计算高度与前,一定要给messageLabel.text赋值

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

    

    return [self.chatCellTool cellHeghit];

}


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

    

    

    XMGChatCell *cell = nil;

    if (indexPath.row % 2 == 0) {//发送方的cell

        cell = [tableView dequeueReusableCellWithIdentifier:SenderCell];

    }else{//接收发方的cell

        cell = [tableView dequeueReusableCellWithIdentifier:ReceiverCell];

    }

    //显示内容

    

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

    

    return cell;

    

    

}



打开  Main.storyboard



XMGChatViewController 控制器中的  table view 中添加  cell


设置 class:XMGChatCell

label:SenderCell

Identifier:SenderCell

background: Purple

Row  Height:73



Content View  中添加 imageView    image:chatListCellHead

x  y width  height:277  5 35  35


设置  约束    勾选 :5  :5

取消选中  Constrain  to margins

勾选 Width:35  Height:35


Content View  中添加 imageView    image:chat_sender_bg

label:messageBg

Stretching:    x  y width  height:0.5 0.7 0 0    拉伸图片

x  y width  height:205  5 67  41


Content View  中添加 label       lines:0

Preferred Width:242    预先宽度  宽度不能超过242

x  y width  height:215  15   42   21


连接 messageLabel  输出口


设置  约束    勾选 :15  :20

取消选中  Constrain  to margins


同时选中  chat_sender_bgmessageLabel


设置约束   点击右下角第一个   勾选 Leading Edges

Trailing Edges

Top Edges

Bottom Edges



找到 约束 Message Label.top     Constrain    10

找到 约束 Message Label.bottom  Constrain    -10

找到 约束 Message Label.leading Constrain    10

找到 约束 Message Label.trailing Constrain    -15




运行



16.聊天界面-发送聊天消息




打开  Main.storyboard


选中  XMGChatViewController  控制器  中的 textView   设置  Return Key :  Send

并连接 delegate   XMGChatViewController  控制器


打开  XMGChatViewController.h


加入  #import "EaseMob.h"


在加入


/** 好友 */

@property (nonatomic, strong) EMBuddy *buddy;




打开  XMGChatViewController.m



在延展中加入 协议  ,UITextViewDelegate


将方法 viewDidLoad  中的


[self.dataSources addObject:@"xcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfa"];


只保留第一个 其余都删除掉



在类中加入方法



#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]];

    

    // 消息类型

    //    @constant eMessageTypeChat            单聊消息 默认

    //    @constant eMessageTypeGroupChat       群聊消息

    //    @constant eMessageTypeChatRoom        聊天室消息

    

    msgObj.messageType = eMessageTypeChat;

    

    // 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];

    

}



打开  XMGAddressBookViewController.m


加入  #import "XMGChatViewController.h"


加入方法


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

    

    //往聊天控制器 传递一个 buddy的值

    id destVC = segue.destinationViewController;

    if ([destVC isKindOfClass:[XMGChatViewController class]]) {

        //获取点击的行

        NSInteger selectedRow = [self.tableView indexPathForSelectedRow].row;

        

        XMGChatViewController *chatVc = destVC;

        chatVc.buddy = self.buddyList[selectedRow];

    }

    

}




运行   2个应用APP之间发送消息



查看控制台



17.聊天界面-加载本地聊天记录


通过沙盒找到 easemobDB  下的 lamcoChat.db  查看 MessageV1



打开   XMGChatCell.h


加入 #import "EaseMob.h"


@property (weak, nonatomic) IBOutlet UILabel *messageLabel;


下面加入


/** 消息模型,内部set方法 显示文字 */

@property (nonatomic, strong) EMMessage *message;



打开  XMGChatCell.m


加入方法


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

    

    _message = message;

    

    // 1.获取消息体

    id body = message.messageBodies[0];

    if ([body isKindOfClass:[EMTextMessageBody class]]) {//文本消息

        EMTextMessageBody *textBody = body;

        self.messageLabel.text = textBody.text;

    }else if([body isKindOfClass:[EMVoiceMessageBody class]]){//语音消息

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

    }

    else{

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

    }

    

    

}



删除  awakeFromNibsetSelected 方法


打开  XMGChatViewController.m




viewDidLoad   方法中的


//初始化数据

[self.dataSources addObject:@"xcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfaxcsafasdfsadfa"];


删除


    self.chatCellTool = [self.tableView dequeueReusableCellWithIdentifier:ReceiverCell];


下面加入


// 显示好友的名字

self.title = self.buddy.username;


// 加载本地数据库聊天记录(MessageV1

[self loadLocalChatRecords];



在类中加入方法


-(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];

}




  heightForRowAtIndexPath  方法中的


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


改为


// 设置label的数据

// 1.获取消息模型

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


self.chatCellTool.message = msg;




  cellForRowAtIndexPath  方法修改如下



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

    

    //1.先获取消息模型

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

    //    EMMessage

    /* from:lamco1 to:lamco7 发送方(自己)

     * from:lamco7 to:lamco1 接收方 (好友)

     */

    

    XMGChatCell *cell = nil;

    if ([message.from isEqualToString:self.buddy.username]) {//接收方

        cell = [tableView dequeueReusableCellWithIdentifier:ReceiverCell];

    }else{//发送方

        cell = [tableView dequeueReusableCellWithIdentifier:SenderCell];

    }

    //显示内容

    cell.message = message;

    

    return cell;

    

    

}



  sendMessage  方法第一句位置加入


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

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

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




// 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];


下面加入


// 3.把消息添加到数据源,然后再刷新表格

[self.dataSources addObject:msgObj];

[self.tableView reloadData];

// 4.把消息显示在顶部

[self scrollToBottom];



在类中加入方法



-(void)scrollToBottom{

    //1.获取最后一行

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

        return;

    }

    

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

    

    [self.tableView scrollToRowAtIndexPath:lastIndex atScrollPosition:UITableViewScrollPositionBottom animated:YES];

}



运行



18.聊天界面-监听消息回复



打开  XMGChatViewController.m


在延展中加入    ,EMChatManagerDelegate



viewDidLoad  方法中的


[self loadLocalChatRecords];


下面加入


// 设置聊天管理器的代理

[[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:nil];




在类中加入方法


#pragma mark 接收好友回复消息

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

#warning from 一定等于当前聊天用户才可以刷新数据

    //test1 - test7

    //test1 - test8

    if ([message.from isEqualToString:self.buddy.username]) {

        //1.把接收的消息添加到数据源

        [self.dataSources addObject:message];

        

        //2.刷新表格

        [self.tableView reloadData];

        

        //3.显示数据到底部

        [self scrollToBottom];

        

    }

    

    

}


运行


以上实现了聊天的收发





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值