集成环信的即时通讯

现在即时通讯比较火,很多公司会用到即时通讯,所以今天给大家讲讲即时通讯,因为没有服务器,所以使用了环信的SDK写了个即时通讯的demo,由于界面比较多,我不会像之前一样直接上代码,而是手把手一点点给大家说,用最简单的代码完成基本的即时通讯功能,尽量使大家看了这篇博客后都能写出一个简单的即时通讯的demo.github地址

上官网注册账号

首先来到环信的官网,然后登陆.没有账号先注册一个.
进去之后创建应用,如图

创建应用界面

点击确定后,来到这个界面,只需要记住应用标示(APPKey)就行,待会儿会在代码里用到它.
屏幕快照 2016-01-04 下午7.18.38.png

然后用cocoapods导入环信SDK,大家可以通过这篇博客来安装cocoapods.

创建项目

打开终端,输入cd,然后将项目入进去回车,就跳到项目地址,输入命令:pod init,然后会生成一个Podfile,双击这个文件,将里面的东西全删了,然后输入:pod 'EaseMobSDK',然后在终端输入命令:pod install(如果不行可以试试:pod install --verbose --no-repo-update).接下来就等着SDK下载安装到项目里了,大概几分钟后就好了.这时候需要双击.xcworkspace的那个文件进去.SDK集成就完成了(不知道为什么官方文档里面写的集成特别复杂,需要导入各种框架,修改很多东西,其实只要终端一条指令就OK了).

AppDelegate

大家还记得刚才的APPKey吧,在AppDelegate里面需要注册使用.

#import "AppDelegate.h"
#import "ViewController.h"
#import 
@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    _window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    _window.backgroundColor = [UIColor whiteColor];
    [_window makeKeyAndVisible];
    
    UINavigationController *nav = [[UINavigationController alloc]initWithRootViewController:[[ViewController alloc]init]];
    _window.rootViewController = nav;
    
    //注册环信
    [[EaseMob sharedInstance]registerSDKWithAppKey:@"xmh123#cdxmh" apnsCertName:@""];
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}

- (void)applicationDidEnterBackground:(UIApplication *)application {
    [[EaseMob sharedInstance] applicationDidEnterBackground:application];
}

- (void)applicationWillEnterForeground:(UIApplication *)application {

    [[EaseMob sharedInstance] applicationWillEnterForeground:application];
}

- (void)applicationDidBecomeActive:(UIApplication *)application {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}

- (void)applicationWillTerminate:(UIApplication *)application {
    [[EaseMob sharedInstance]applicationWillTerminate:application];
}

@end
登陆界面
登陆界面

看看这部分的代码吧.

#import "ViewController.h"
#import "RegisterViewController.h"
#import "FriendListViewController.h"
#import 
@interface ViewController ()
@property(nonatomic, strong)UITextField *userNameTextField;//用户名
@property(nonatomic, strong)UITextField *passwordTextField;//密码
@property(nonatomic, strong)UIButton *loginButton;          //登陆按钮
@property(nonatomic, strong)UIButton *registerButton;      //注册按钮
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.navigationController.navigationBar.translucent = NO;
    self.title = @"登陆界面";
    
    UILabel *usernameLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, 100, 80, 50)];
    usernameLabel.text = @"用户名";
    usernameLabel.font = [UIFont systemFontOfSize:25];
    [self.view addSubview:usernameLabel];
    
    _userNameTextField = [[UITextField alloc]initWithFrame:CGRectMake(usernameLabel.frame.origin.x + usernameLabel.frame.size.width + 10, usernameLabel.frame.origin.y, 250, 50)];
    _userNameTextField.borderStyle = 3;
    _userNameTextField.placeholder = @"请输入用户名";
    [self.view addSubview:_userNameTextField];
    
    UILabel *passwordLabel = [[UILabel alloc]initWithFrame:CGRectMake(usernameLabel.frame.origin.x, usernameLabel.frame.origin.y + usernameLabel.frame.size.height + 10, usernameLabel.frame.size.width, usernameLabel.frame.size.height)];
    passwordLabel.text = @"密码";
    passwordLabel.font = [UIFont systemFontOfSize:25];
    [self.view addSubview:passwordLabel];
    
    _passwordTextField = [[UITextField alloc]initWithFrame:CGRectMake(_userNameTextField.frame.origin.x, passwordLabel.frame.origin.y, _userNameTextField.frame.size.width, _userNameTextField.frame.size.height)];
    _passwordTextField.placeholder = @"请输入密码";
    _passwordTextField.borderStyle = 3;
    [self.view addSubview:_passwordTextField];
    
    _loginButton = [UIButton buttonWithType:UIButtonTypeSystem];
    _loginButton.frame = CGRectMake(170, 300, 50, 50);
    _loginButton.titleLabel.font = [UIFont systemFontOfSize:25];
    [_loginButton setTitle:@"登陆" forState:UIControlStateNormal];
    [_loginButton addTarget:self action:@selector(didClickLoginButton) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_loginButton];
    
    _registerButton = [UIButton buttonWithType:UIButtonTypeSystem];
    _registerButton.frame = CGRectMake(170, 410, 50, 50);
    _registerButton.titleLabel.font = [UIFont systemFontOfSize:25];
    [_registerButton setTitle:@"注册" forState:UIControlStateNormal];
    [_registerButton addTarget:self action:@selector(jumpToRegister) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_registerButton];
}

-(void)didClickLoginButton
{
    [[EaseMob sharedInstance].chatManager asyncLoginWithUsername:_userNameTextField.text password:_passwordTextField.text completion:^(NSDictionary *loginInfo, EMError *error) {
        
        if (!error) {
            //如果验证用户名和密码没有问题就跳转到好友列表界面
            [self.navigationController pushViewController:[[FriendListViewController alloc]init] animated:YES];
            
        } else {
            
            // 显示错误信息的警告
            NSLog(@"%@",error);
        }
    } onQueue:dispatch_get_main_queue()];

}

-(void)jumpToRegister
{
//跳转到注册界面
    RegisterViewController *registerVC = [[RegisterViewController alloc]init];
    [self.navigationController presentViewController:registerVC animated:YES completion:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

这个界面很简单,大部分都是界面搭建,当点击登陆时会调用

[[EaseMob sharedInstance].chatManager asyncLoginWithUsername:_userNameTextField.text password:_passwordTextField.text completion:^(NSDictionary *loginInfo, EMError *error)

这个方法有2个参数,一个用户名,一个是密码,很容易猜到这就是验证你的用户名和密码是否正确,如果正确就跳转到好友列表界面,如果不对就会在控制台打印相应的错误.
点击注册就跳转到注册界面.

注册界面
注册界面

由于第一次登陆时没有账号,所以先得注册.先看看代码:

#import "RegisterViewController.h"
#import 
@interface RegisterViewController ()
@property(nonatomic, strong)UITextField *userNameTextField;//用户名
@property(nonatomic, strong)UITextField *passwordTextField;//密码
@property(nonatomic, strong)UIButton *registerButton;      //注册按钮
@end

@implementation RegisterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];
    self.navigationController.navigationBar.translucent = NO;
    self.title = @"登陆界面";
    
    UILabel *usernameLabel = [[UILabel alloc]initWithFrame:CGRectMake(20, 100, 80, 50)];
    usernameLabel.text = @"用户名";
    usernameLabel.font = [UIFont systemFontOfSize:25];
    [self.view addSubview:usernameLabel];
    
    _userNameTextField = [[UITextField alloc]initWithFrame:CGRectMake(usernameLabel.frame.origin.x + usernameLabel.frame.size.width + 10, usernameLabel.frame.origin.y, 250, 50)];
    _userNameTextField.borderStyle = 3;
    _userNameTextField.placeholder = @"请输入用户名";
    [self.view addSubview:_userNameTextField];
    
    UILabel *passwordLabel = [[UILabel alloc]initWithFrame:CGRectMake(usernameLabel.frame.origin.x, usernameLabel.frame.origin.y + usernameLabel.frame.size.height + 10, usernameLabel.frame.size.width, usernameLabel.frame.size.height)];
    passwordLabel.text = @"密码";
    passwordLabel.font = [UIFont systemFontOfSize:25];
    [self.view addSubview:passwordLabel];
    
    _passwordTextField = [[UITextField alloc]initWithFrame:CGRectMake(_userNameTextField.frame.origin.x, passwordLabel.frame.origin.y, _userNameTextField.frame.size.width, _userNameTextField.frame.size.height)];
    _passwordTextField.placeholder = @"请输入密码";
    _passwordTextField.borderStyle = 3;
    [self.view addSubview:_passwordTextField];
    
    _registerButton = [UIButton buttonWithType:UIButtonTypeSystem];
    _registerButton.frame = CGRectMake(170, 330, 50, 50);
    _registerButton.titleLabel.font = [UIFont systemFontOfSize:25];
    [_registerButton setTitle:@"注册" forState:UIControlStateNormal];
    [_registerButton addTarget:self action:@selector(didClickedRegisterButton:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:_registerButton];
    
    UIButton *backButton = [UIButton buttonWithType:UIButtonTypeSystem];
    backButton.frame = CGRectMake(170, 280, 50, 50);
    backButton.titleLabel.font = [UIFont systemFontOfSize:25];
    [backButton setTitle:@"返回" forState:UIControlStateNormal];
    [backButton addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:backButton];
}

-(void)backAction
{
    [self dismissViewControllerAnimated:YES completion:nil];
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//点击屏幕时让键盘回收
    [_passwordTextField resignFirstResponder];
    [_userNameTextField resignFirstResponder];
}

-(void)didClickedRegisterButton:(id)sender
{
//  登陆和注册有3种方法: 1. 同步方法 2. 通过delegate回调的异步方法。3.block异步方法
    //其中官方推荐使用block异步方法,所以我这里就用block异步方法

    //开始注册
    [[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:_userNameTextField.text password:_passwordTextField.text withCompletion:^(NSString *username, NSString *password, EMError *error) {
        if (!error) {
            NSLog(@"注册成功");
            
            [self dismissViewControllerAnimated:YES completion:nil];
        }
        else
        {
            NSLog(@"%@",error);
        }
    } onQueue:dispatch_get_main_queue()];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
}

@end

这个界面也特别简单,除了界面搭建,就只有这个方法:

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

一共两个参数,就是用户名和密码,然后判断用户名和密码是否可用,如果可用就返回到登陆界面.

好友列表界面
好友列表界面

这里我只加了一个好友叫xiaomei.
好友界面是怎么样的呢,大家先看看代码:

#import "FriendListViewController.h"
#import "AddFriendViewController.h"
#import "ChatViewController.h"
#import 
@interface FriendListViewController ()
@property(nonatomic, strong)NSMutableArray *listArray;
@property(nonatomic, strong)UITableView *tableView;
@end

@implementation FriendListViewController

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    
    }
-(void)loadView
{
    [super loadView];
    self.view.backgroundColor = [UIColor whiteColor];
    //左侧注销按钮
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"注销" style:UIBarButtonItemStylePlain target:self action:@selector(didClickedCancelButton)];
    self.title = @"好友";
    
    [[EaseMob sharedInstance].chatManager asyncFetchBuddyListWithCompletion:^(NSArray *buddyList, EMError *error) {
        
        if (!error) {
            NSLog(@"获取成功 -- %@", buddyList);
            
            [_listArray removeAllObjects];
            [_listArray addObjectsFromArray:buddyList];
            [_tableView reloadData];
        }
    } onQueue:dispatch_get_main_queue()];

}

- (void)viewDidLoad {
    [super viewDidLoad];
    _listArray = [NSMutableArray new];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addbuttonAction)];
    _tableView = [[UITableView alloc]initWithFrame:self.view.frame];
    _tableView.delegate = self;
    _tableView.dataSource = self;
    _tableView.tableFooterView = [[UIView alloc]init];
    [self.view addSubview:_tableView];
    //签协议
    [ [EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:dispatch_get_main_queue()];
}

-(void)didClickedCancelButton
{
    //注销用户
    [[EaseMob sharedInstance].chatManager asyncLogoffWithUnbindDeviceToken:YES];
    [self.navigationController popViewControllerAnimated:YES];
}

-(void)addbuttonAction
{
    [self.navigationController pushViewController:[[AddFriendViewController alloc]init] animated:YES];
}

# pragma mark - Table View Data Source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    return _listArray.count;
}

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 50;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *identifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
    }
    
    EMBuddy * buddy = _listArray[indexPath.row];
    
    cell.textLabel.text = buddy.username;
    
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    
    ChatViewController * chatVC = [[ChatViewController alloc]init];
    
    EMBuddy * buddy = _listArray[indexPath.row];
    
    chatVC.name = buddy.username;
    
    [self.navigationController pushViewController:chatVC animated:YES];
}
-(void)didReceiveBuddyRequest:(NSString *)username message:(NSString *)message
{
    UIAlertController * alertController = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"收到来自%@的请求", username] message:message preferredStyle:(UIAlertControllerStyleAlert)];
    UIAlertAction * acceptAction = [UIAlertAction actionWithTitle:@"好" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction *  action) {
        EMError * error;
        // 同意好友请求的方法
        if ([[EaseMob sharedInstance].chatManager acceptBuddyRequest:username error:&error] && !error) {
            NSLog(@"发送同意成功");
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                [[EaseMob sharedInstance].chatManager asyncFetchBuddyListWithCompletion:^(NSArray *buddyList, EMError *error) {
                    
                    if (!error) {
                        NSLog(@"获取成功 -- %@", buddyList);
                        
                        [_listArray removeAllObjects];
                        [_listArray addObjectsFromArray:buddyList];
                        [_tableView reloadData];
                    }
                } onQueue:dispatch_get_main_queue()];
            });
        }
    }];
    UIAlertAction * rejectAction = [UIAlertAction actionWithTitle:@"滚" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
        EMError * error;
        // 拒绝好友请求的方法
        if ([[EaseMob sharedInstance].chatManager rejectBuddyRequest:username reason:@"滚, 快滚!" error:&error] && !error) {
            NSLog(@"发送拒绝成功");
        }
    }];
    [alertController addAction:acceptAction];
    [alertController addAction:rejectAction];
    [self showDetailViewController:alertController sender:nil];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

首先,使用下面这个方法获取到所有的好友,然后将好友放入你的数组,这样好友的信息都在数组里了

[[EaseMob sharedInstance].chatManager asyncFetchBuddyListWithCompletion:^(NSArray *buddyList, EMError *error) {
        
        if (!error) {
            NSLog(@"获取成功 -- %@", buddyList);
            
            [_listArray removeAllObjects];
            [_listArray addObjectsFromArray:buddyList];
            [_tableView reloadData];
        }
    } onQueue:dispatch_get_main_queue()];

tableView没行的信息通过下面这个方法,刚才已经把所有好友的信息方法数组里了,那么就可以通过EMBuddy * buddy = _listArray[indexPath.row]这个方法获取单个好友信息,用 cell.textLabel.text = buddy.username给每个cell的text赋值.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *identifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
    }
    
    EMBuddy * buddy = _listArray[indexPath.row];
    
    cell.textLabel.text = buddy.username;
    
    return cell;
}

当别人想加你为好友时,会调用这个方法.先弹出一个提示框,然后根据你的选择而去接受或者拒绝.如果接受,就重新导入一遍数据,然后刷新tableView.如果拒绝就调用拒绝的方法.这并不难理解吧.



-(void)didReceiveBuddyRequest:(NSString *)username message:(NSString *)message
{
 UIAlertController * alertController = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"收到来自%@的请求", username] message:message preferredStyle:(UIAlertControllerStyleAlert)];
    UIAlertAction * acceptAction = [UIAlertAction actionWithTitle:@"好" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction *  action) {
        EMError * error;
        // 同意好友请求的方法
        if ([[EaseMob sharedInstance].chatManager acceptBuddyRequest:username error:&error] && !error) {
            NSLog(@"发送同意成功");
                [[EaseMob sharedInstance].chatManager asyncFetchBuddyListWithCompletion:^(NSArray *buddyList, EMError *error) {
                    
                    if (!error) {
                        NSLog(@"获取成功 -- %@", buddyList);
                        
                        [_listArray removeAllObjects];
                        [_listArray addObjectsFromArray:buddyList];
                        [_tableView reloadData];
                    }
                } onQueue:dispatch_get_main_queue()];
        
        }
    }];
    UIAlertAction * rejectAction = [UIAlertAction actionWithTitle:@"滚" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
        EMError * error;
        // 拒绝好友请求的方法
        if ([[EaseMob sharedInstance].chatManager rejectBuddyRequest:username reason:@"滚, 快滚!" error:&error] && !error) {
            NSLog(@"发送拒绝成功");
        }
    }];
    [alertController addAction:acceptAction];
    [alertController addAction:rejectAction];
    [self showDetailViewController:alertController sender:nil];
聊天界面
聊天界面

在看聊天界面之前先需要自定义一个聊天输入框,就是下面那个带一个textfield和button的.

DialogBoxView.m
#import "DialogBoxView.h"
@interface DialogBoxView ()
@property (nonatomic, strong) UITextField * draftTextField;
@property (nonatomic, strong) UIButton * sendButton;

@end

@implementation DialogBoxView

- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        
        [self initView];
    }
    return self;
}

- (void)initView{
    
    [self setBackgroundColor:[UIColor colorWithWhite:0.9 alpha:1]];
    
    _draftTextField = [[UITextField alloc] initWithFrame:CGRectMake(5, 5, self.frame.size.width - 100, self.frame.size.height - 10)];
    [_draftTextField setBorderStyle:(UITextBorderStyleRoundedRect)];
    [_draftTextField setPlaceholder:@"说点什么呢"];
    [_draftTextField setFont:[UIFont systemFontOfSize:13]];
    [self addSubview:_draftTextField];
    
    _sendButton = [UIButton buttonWithType:(UIButtonTypeCustom)];
    [_sendButton setFrame:CGRectMake(self.frame.size.width - 90, 5, 85, self.frame.size.height - 10)];
    [_sendButton setBackgroundColor:[UIColor colorWithRed:1 green:0 blue:128 / 255.0 alpha:1]];
    [_sendButton setTitle:@"发送" forState:(UIControlStateNormal)];
    [_sendButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [_sendButton.titleLabel setFont:[UIFont boldSystemFontOfSize:15]];
    [_sendButton.layer setMasksToBounds:YES];
    [_sendButton.layer setCornerRadius:4];
    [_sendButton addTarget:self action:@selector(didSendButtonClicked:) forControlEvents:(UIControlEventTouchUpInside)];
    [self addSubview:_sendButton];
}

- (void)didSendButtonClicked:(UIButton *)sender {
    
    if (self.buttonClicked) {
        self.buttonClicked(_draftTextField.text);
    }
    _draftTextField.text = @"";
}

- (NSString *)draftText {
    
    return _draftTextField.text;
}

/*
 // Only override drawRect: if you perform custom drawing.
 // An empty implementation adversely affects performance during animation.
 - (void)drawRect:(CGRect)rect {
 // Drawing code
 }
 */

@end

这个简单的自定义view没什么好说的,关键是他的.h文件

DialogBoxView.h
#import 
typedef void(^ButtonClicked)(NSString * draftText);
@interface DialogBoxView : UIView
@property (nonatomic, copy) ButtonClicked buttonClicked;
@end

这里用到一个block,当点击按钮时会调用这个block.

接下看看聊天界面的代码吧.


#import "ChatViewController.h"
#import "DialogBoxView.h"
#import 

@interface ChatViewController ()
@property(nonatomic, strong)UITableView *tableView;
@property(nonatomic, strong)EMConversation *conversation;
@property(nonatomic, strong)DialogBoxView *dialogBoxView;
@end

@implementation ChatViewController

-(void)loadView
{
    [super loadView];
    self.title = _name;
    self.navigationController.navigationBar.translucent = NO;
    _tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 50)];
    _tableView.delegate = self;
    _tableView.dataSource = self;
    _tableView.tableFooterView = [[UIView alloc]init];
    [self.view addSubview:_tableView];
}

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    [_tableView setAllowsSelection:NO];
    
    [self registerForKeyboardNotifications];
    
    _dialogBoxView = [[DialogBoxView alloc]initWithFrame:CGRectMake(0, self.view.frame.size.height - 114, self.view.frame.size.width, 50)];
    
    __weak typeof(self) weakSelf = self;
    
    _dialogBoxView.buttonClicked = ^(NSString * draftText){
        
        [weakSelf sendMessageWithDraftText:draftText];
    };
    
    [self.view addSubview:_dialogBoxView];
    
    [[EaseMob sharedInstance].chatManager addDelegate:self delegateQueue:dispatch_get_main_queue()];
    
    [self reloadChatRecords];
}

- (void)viewWillDisappear:(BOOL)animated {
    
    [super viewWillDisappear:animated];
    
    // 移除通知中心
    [self removeForKeyboardNotifications];
    
    // 移除代理
    [[EaseMob sharedInstance].chatManager removeDelegate:self];
}

# pragma mark - Send Message
/**
 *  使用草稿发送一条信息
 *
 *  @param draftText 草稿
 */
- (void)sendMessageWithDraftText:(NSString *)draftText {
    
    EMChatText * chatText = [[EMChatText alloc] initWithText:draftText];
    EMTextMessageBody * body = [[EMTextMessageBody alloc] initWithChatObject:chatText];
    
    // 生成message
    EMMessage * message = [[EMMessage alloc] initWithReceiver:self.name bodies:@[body]];
    message.messageType = eMessageTypeChat; // 设置为单聊消息
    
    [[EaseMob sharedInstance].chatManager asyncSendMessage:message progress:nil prepare:^(EMMessage *message, EMError *error) {
        
        // 准备发送
    } onQueue:dispatch_get_main_queue() completion:^(EMMessage *message, EMError *error) {
        
        [self reloadChatRecords];
        // 发送完成
    } onQueue:dispatch_get_main_queue()];
}

# pragma mark - Receive Message
/**
 *  当收到了一条消息时
 *
 *  @param message 消息构造体
 */
- (void)didReceiveMessage:(EMMessage *)message {
    
    [self reloadChatRecords];
}

# pragma mark - Reload Chat Records
/**
 *  重新加载TableView上面显示的聊天信息, 并移动到最后一行
 */
- (void)reloadChatRecords {
    
    _conversation = [[EaseMob sharedInstance].chatManager conversationForChatter:self.name conversationType:eConversationTypeChat];
    
    [_tableView reloadData];
    
    if ([_conversation loadAllMessages].count > 0) {
        
        [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:[_conversation loadAllMessages].count - 1 inSection:0] atScrollPosition:(UITableViewScrollPositionBottom) animated:YES];
    }
}

# pragma mark - Keyboard Method
/**
 *  注册通知中心
 */
- (void)registerForKeyboardNotifications
{
    // 使用NSNotificationCenter 注册观察当键盘要出现时
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    
    // 使用NSNotificationCenter 注册观察当键盘要隐藏时
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didKeyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
}

/**
 *  移除通知中心
 */
- (void)removeForKeyboardNotifications {
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

/**
 *  键盘将要弹出
 *
 *  @param notification 通知
 */
- (void)didKeyboardWillShow:(NSNotification *)notification {
    
    NSDictionary * info = [notification userInfo];
    
    CGSize keyboardSize = [[info objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    
    NSLog(@"%f", keyboardSize.height);
    
    //输入框位置动画加载
    [self begainMoveUpAnimation:keyboardSize.height];
}

/**
 *  键盘将要隐藏
 *
 *  @param notification 通知
 */
- (void)didKeyboardWillHide:(NSNotification *)notification {
    
    [self begainMoveUpAnimation:0];
}

/**
 *  开始执行键盘改变后对应视图的变化
 *
 *  @param height 键盘的高度
 */
- (void)begainMoveUpAnimation:(CGFloat)height {
    
    [UIView animateWithDuration:0.3 animations:^{
        
        [_dialogBoxView setFrame:CGRectMake(0, self.view.frame.size.height - (height + 40), _dialogBoxView.frame.size.width, _dialogBoxView.frame.size.height)];
    }];
    
    
    [_tableView layoutIfNeeded];
    
    if ([_conversation loadAllMessages].count > 1) {
        
        [_tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:_conversation.loadAllMessages.count - 1 inSection:0] atScrollPosition:(UITableViewScrollPositionMiddle) animated:YES];
    }
}

# pragma mark - Table View Data Source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    
    return _conversation.loadAllMessages.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *identifier = @"cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
    if (!cell) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
    }
    
    EMMessage * message = _conversation.loadAllMessages[indexPath.row];
    
    EMTextMessageBody * body = [message.messageBodies lastObject];
    
    //判断发送的人是否是当前聊天的人,左边是对面发过来的,右边是自己发过去的
    if ([message.to isEqualToString:self.name]) {
        
        cell.detailTextLabel.text = body.text;
        cell.detailTextLabel.textColor = [UIColor redColor];
        cell.textLabel.text = @"";
        cell.textLabel.textColor = [UIColor blueColor];
        
    } else {
        
        cell.detailTextLabel.text = @"";
        cell.textLabel.text = body.text;
        cell.detailTextLabel.textColor = [UIColor redColor];
        cell.textLabel.textColor = [UIColor blueColor];
    }
    
    return cell;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

这里面也没什么难点,也有注释,相信大家能懂.
最后看看最后的成果图吧.

成品图

好了,今天就到这里,祝大家天天开心

你可能感兴趣的:(集成环信的即时通讯)