現(xiàn)在即時通訊比較火,很多公司會用到即時通訊,所以今天給大家講講即時通訊,因為沒有服務(wù)器,所以使用了環(huán)信的SDK寫了個即時通訊的demo,由于界面比較多,我不會像之前一樣直接上代碼,而是手把手一點點給大家說,用最簡單的代碼完成基本的即時通訊功能,盡量使大家看了這篇博客后都能寫出一個簡單的即時通訊的demo.github地址
上官網(wǎng)注冊賬號
首先來到環(huán)信的官網(wǎng),然后登陸.沒有賬號先注冊一個.
進去之后創(chuàng)建應(yīng)用,如圖
點擊確定后,來到這個界面,只需要記住應(yīng)用標(biāo)示(APPKey)就行,待會兒會在代碼里用到它.
然后用cocoapods導(dǎo)入環(huán)信SDK,大家可以通過這篇博客來安裝cocoapods.
創(chuàng)建項目
打開終端,輸入cd,然后將項目入進去回車,就跳到項目地址,輸入命令:pod init,然后會生成一個Podfile,雙擊這個文件,將里面的東西全刪了,然后輸入:pod 'EaseMobSDK',然后在終端輸入命令:pod install(如果不行可以試試:pod install --verbose --no-repo-update).接下來就等著SDK下載安裝到項目里了,大概幾分鐘后就好了.這時候需要雙擊.xcworkspace的那個文件進去.SDK集成就完成了(不知道為什么官方文檔里面寫的集成特別復(fù)雜,需要導(dǎo)入各種框架,修改很多東西,其實只要終端一條指令就OK了).
AppDelegate
大家還記得剛才的APPKey吧,在AppDelegate里面需要注冊使用.
#import "AppDelegate.h"
#import "ViewController.h"
#import <EaseMob.h>
@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;
//注冊環(huán)信
[[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 <EaseMob.h>
@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) {
//如果驗證用戶名和密碼沒有問題就跳轉(zhuǎn)到好友列表界面
[self.navigationController pushViewController:[[FriendListViewController alloc]init] animated:YES];
} else {
// 顯示錯誤信息的警告
NSLog(@"%@",error);
}
} onQueue:dispatch_get_main_queue()];
}
-(void)jumpToRegister
{
//跳轉(zhuǎn)到注冊界面
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
這個界面很簡單,大部分都是界面搭建,當(dāng)點擊登陸時會調(diào)用
[[EaseMob sharedInstance].chatManager asyncLoginWithUsername:_userNameTextField.text password:_passwordTextField.text completion:^(NSDictionary *loginInfo, EMError *error)
這個方法有2個參數(shù),一個用戶名,一個是密碼,很容易猜到這就是驗證你的用戶名和密碼是否正確,如果正確就跳轉(zhuǎn)到好友列表界面,如果不對就會在控制臺打印相應(yīng)的錯誤.
點擊注冊就跳轉(zhuǎn)到注冊界面.
注冊界面
由于第一次登陸時沒有賬號,所以先得注冊.先看看代碼:
#import "RegisterViewController.h"
#import <EaseMob.h>
@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<UITouch *> *)touches withEvent:(UIEvent *)event
{
//點擊屏幕時讓鍵盤回收
[_passwordTextField resignFirstResponder];
[_userNameTextField resignFirstResponder];
}
-(void)didClickedRegisterButton:(id)sender
{
// 登陸和注冊有3種方法: 1. 同步方法 2. 通過delegate回調(diào)的異步方法晒衩。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)
一共兩個參數(shù),就是用戶名和密碼,然后判斷用戶名和密碼是否可用,如果可用就返回到登陸界面.
好友列表界面
這里我只加了一個好友叫xiaomei.
好友界面是怎么樣的呢,大家先看看代碼:
#import "FriendListViewController.h"
#import "AddFriendViewController.h"
#import "ChatViewController.h"
#import <EaseMob.h>
@interface FriendListViewController ()<UITableViewDataSource,UITableViewDelegate,EMChatManagerDelegate,EMChatManagerBuddyDelegate>
@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];
//左側(cè)注銷按鈕
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];
//簽協(xié)議
[ [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(@"發(fā)送同意成功");
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(@"發(fā)送拒絕成功");
}
}];
[alertController addAction:acceptAction];
[alertController addAction:rejectAction];
[self showDetailViewController:alertController sender:nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
首先,使用下面這個方法獲取到所有的好友,然后將好友放入你的數(shù)組,這樣好友的信息都在數(shù)組里了
[[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沒行的信息通過下面這個方法,剛才已經(jīng)把所有好友的信息方法數(shù)組里了,那么就可以通過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;
}
當(dāng)別人想加你為好友時,會調(diào)用這個方法.先彈出一個提示框,然后根據(jù)你的選擇而去接受或者拒絕.如果接受,就重新導(dǎo)入一遍數(shù)據(jù),然后刷新tableView.如果拒絕就調(diào)用拒絕的方法.這并不難理解吧.
-(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(@"發(fā)送同意成功");
[[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(@"發(fā)送拒絕成功");
}
}];
[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:@"發(fā)送" 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沒什么好說的,關(guān)鍵是他的.h文件
DialogBoxView.h
#import <UIKit/UIKit.h>
typedef void(^ButtonClicked)(NSString * draftText);
@interface DialogBoxView : UIView
@property (nonatomic, copy) ButtonClicked buttonClicked;
@end
這里用到一個block,當(dāng)點擊按鈕時會調(diào)用這個block.
接下看看聊天界面的代碼吧.
#import "ChatViewController.h"
#import "DialogBoxView.h"
#import <EaseMob.h>
@interface ChatViewController ()<EMChatManagerDelegate,UITableViewDelegate,UITableViewDataSource>
@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
/**
* 使用草稿發(fā)送一條信息
*
* @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; // 設(shè)置為單聊消息
[[EaseMob sharedInstance].chatManager asyncSendMessage:message progress:nil prepare:^(EMMessage *message, EMError *error) {
// 準(zhǔn)備發(fā)送
} onQueue:dispatch_get_main_queue() completion:^(EMMessage *message, EMError *error) {
[self reloadChatRecords];
// 發(fā)送完成
} onQueue:dispatch_get_main_queue()];
}
# pragma mark - Receive Message
/**
* 當(dāng)收到了一條消息時
*
* @param message 消息構(gòu)造體
*/
- (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 注冊觀察當(dāng)鍵盤要出現(xiàn)時
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didKeyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
// 使用NSNotificationCenter 注冊觀察當(dāng)鍵盤要隱藏時
[[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];
}
/**
* 開始執(zhí)行鍵盤改變后對應(yīng)視圖的變化
*
* @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];
//判斷發(fā)送的人是否是當(dāng)前聊天的人,左邊是對面發(fā)過來的,右邊是自己發(fā)過去的
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
這里面也沒什么難點,也有注釋,相信大家能懂.
最后看看最后的成果圖吧.
好了,今天就到這里,祝大家天天開心