iOS 最新環(huán)信即時通訊單聊集成

在做App開發(fā)的時候柿顶,我們往往會用到即時通訊唯蝶,而其中最常用的就是單聊了。
今天就給大家分享一下最新的環(huán)信3.x單聊集成详瑞。在文章結束處有Demo地址掂林。

首先要有一個環(huán)信賬號

點擊到環(huán)信官網注冊按照官方文檔來完成注冊開發(fā)者賬號和注冊項目

制作并上傳證書

按照文檔注冊證書
如果不需要實現離線推送功能,請忽略這步坝橡。一般我們都需要離線功能泻帮。

SDK導入

通過Cocoapods下載地址
不包含實時語音版本SDK(HyphenateSDK),引用時 #import <HyphenateSDK/EMSDK.h>
pod 'HyphenateSDK', :git => 'https://github.com/easemob/hyphenate-cocoapods.git'
包含實時語音版本SDK(HyphenateFullSDK)计寇,引用時 #import <HyphenateFullSDK/EMSDKFull.h>
pod 'HyphenateFullSDK', :git => 'https://github.com/easemob/hyphenate-full-cocoapods.git'

注意導入的SDK中不包含EaseUI锣杂,如果要使用EaseUI,要導入如下文件番宁,ChatView是一個官方的單聊控制器文件夾元莫,如果不需要可以不導入

初始化SDK和EaseUI

#import "AppDelegate.h"
#import <HyphenateFullSDK/EMSDKFull.h>

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //AppKey:注冊的appKey(在你創(chuàng)建項目的時候會獲得appKey)
    //apnsCertName:推送證書名(不需要加后綴)
    EMOptions *options = [EMOptions optionsWithAppkey:@"mmengyiqu#will"];
    options.apnsCertName = @"istore_dev";
    [[EMClient sharedClient] initializeSDKWithOptions:options];
    
    //初始化EaseUI
    [[EaseSDKHelper shareHelper] easemobApplication:application
                      didFinishLaunchingWithOptions:launchOptions
                                             appkey:@"mmengyiqu#will"
                                       apnsCertName:@"istore_dev"
                                        otherConfig:@{kSDKConfigEnableConsoleLogger:[NSNumber numberWithBool:YES]}];
      
    return YES;
}
// App進入后臺
- (void)applicationDidEnterBackground:(UIApplication *)application
{
    [[EMClient sharedClient] applicationDidEnterBackground:application];
}

// App將要從后臺返回
- (void)applicationWillEnterForeground:(UIApplication *)application
{
    [[EMClient sharedClient] applicationWillEnterForeground:application];
}

登錄界面


代碼如下

#import "ViewController.h"
#import <HyphenateFullSDK/EMSDKFull.h>

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextField *nameTextField;//用戶名
@property (weak, nonatomic) IBOutlet UITextField *passwordTextField;//密碼

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}
- (IBAction)loginAction:(UIButton *)sender {
    
    //登錄
    EMError *error = [[EMClient sharedClient] loginWithUsername:self.nameTextField.text password:self.passwordTextField.text];
    if (!error) {
        NSLog(@"登陸成功");
        
        //從數據庫中獲得數據
        [[EMClient sharedClient].chatManager loadAllConversationsFromDB];
        
        UINavigationController* nv=[[UIStoryboard storyboardWithName:@"Main" bundle:nil] instantiateViewControllerWithIdentifier:@"FriendListNavigationController"];
        [self presentViewController:nv animated:YES completion:^{
        
        }];
    }else{
        NSLog(@"登錄失敗");
    }
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
  • 登錄時掉用這個接口,username是用戶名蝶押,password是密碼
EMError *error = [[EMClient sharedClient] loginWithUsername: password: ];if (!error) { NSLog(@"登陸成功");}
  • 登錄成功之后從數據庫中獲得之前的聊天記錄柒竞,如果沒有這句,那么每當你退出之后再進入聊天播聪,記錄就消失了
 [[EMClient sharedClient].chatManager loadAllConversationsFromDB];

注冊界面


代碼如下

#import "RegisterViewController.h"
#import <HyphenateFullSDK/EMSDKFull.h>

@interface RegisterViewController ()
@property (weak, nonatomic) IBOutlet UITextField *nameTextField;//用戶名
@property (weak, nonatomic) IBOutlet UITextField *password;//密碼

@end

@implementation RegisterViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}
- (IBAction)SureAction:(UIButton *)sender {
    
    //注冊
    EMError *error = [[EMClient sharedClient] registerWithUsername:self.nameTextField.text password:self.password.text];
    if (error==nil) {
        NSLog(@"注冊成功");
        [self dismissViewControllerAnimated:YES completion:^{
            
        }];
        
    }else{
        NSLog(@"注冊失敗");
    }
}

- (IBAction)cancelAction:(UIButton *)sender {
    [self dismissViewControllerAnimated:YES completion:^{
        
    }];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
  • 注冊時調用這個接口朽基,username是用戶名,password是密碼
EMError *error = [[EMClient sharedClient] registerWithUsername: password: ];if (error==nil) { NSLog(@"注冊成功");}

添加好友頁


代碼如下

#import "AddFriendViewController.h"
#import <HyphenateFullSDK/EMSDKFull.h>

@interface AddFriendViewController ()
@property (weak, nonatomic) IBOutlet UITextField *nameTextField;

@end

@implementation AddFriendViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

- (IBAction)addFriendAction:(UIButton *)sender {

    //發(fā)送添加好友申請
    EMError *error = [[EMClient sharedClient].contactManager addContact:self.nameTextField.text message:@"我想加您為好友"];
    if (!error) {
        NSLog(@"添加成功");
        
        [self.navigationController popViewControllerAnimated:YES];
    }else{
        NSLog(@"添加好友失斃胩铡-------%@",error);
    }
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self.view endEditing:YES];
}
  • 發(fā)送添加好友申請
EMError *error = [[EMClient sharedClient].contactManager addContact:@"6001" message:@"我想加您為好友"];
if (!error) { NSLog(@"添加成功");}

好友界面


代碼如下

#import "FriendListTableViewController.h"
#import <HyphenateFullSDK/EMSDKFull.h>
#import "FriendListTableViewCell.h"
#import "EaseMessageViewController.h"http://單聊基礎界面
#import "ChatViewController.h"http://單聊chat界面

@interface FriendListTableViewController ()<EMContactManagerDelegate>
{
    NSMutableArray* _nameArr;//接收好友列表
}

@end

@implementation FriendListTableViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.title=@"我的好友";
    self.tableView.backgroundColor=[UIColor whiteColor];
    _nameArr=[[NSMutableArray alloc]init];
    
    [self getFridendListAndReloadTableView];//獲取好友列表并刷新tableView
    
    //注冊好友回調
    [[EMClient sharedClient].contactManager addDelegate:self delegateQueue:nil];
}

//獲取好友列表并刷新tableView
-(void)getFridendListAndReloadTableView
{
    //獲取好友列表
    EMError *error = nil;
    NSArray *userlist = [[EMClient sharedClient].contactManager getContactsFromServerWithError:&error];
    if (!error) {
        NSLog(@"好友獲取成功 -- %@",userlist);
        
        [_nameArr removeAllObjects];
        [_nameArr addObjectsFromArray:userlist];
        [self.tableView reloadData];
    }
}

#pragma mark - 監(jiān)聽添加好友回調
//監(jiān)聽回調
/*!
 *  用戶A發(fā)送加用戶B為好友的申請稼虎,用戶B會收到這個回調
 *
 *  @param aUsername   用戶名
 *  @param aMessage    附屬信息
 */
- (void)didReceiveFriendInvitationFromUsername:(NSString *)aUsername
                                       message:(NSString *)aMessage
{
    UIAlertController * alertController = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"收到來自%@的請求", aUsername] message:aMessage preferredStyle:(UIAlertControllerStyleAlert)];
    
    UIAlertAction * acceptAction = [UIAlertAction actionWithTitle:@"好" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action)
    {
    
        // 同意好友請求的方法
        EMError *agreeError = [[EMClient sharedClient].contactManager acceptInvitationForUsername:aUsername];
        if (!agreeError) {
            NSLog(@"發(fā)送同意成功");
            
            [self getFridendListAndReloadTableView];//獲取好友列表并刷新tableView
        }
    }];
    
    UIAlertAction * rejectAction = [UIAlertAction actionWithTitle:@"NO" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
        
        // 拒絕好友請求的方法
        EMError *rejectError = [[EMClient sharedClient].contactManager declineInvitationForUsername:aUsername];
        if (!rejectError) {
            NSLog(@"發(fā)送拒絕成功");
        }
    }];
    
    [alertController addAction:acceptAction];
    [alertController addAction:rejectAction];
    [self showDetailViewController:alertController sender:nil];
}

//好友申請?zhí)幚斫Y果回調
//監(jiān)聽回調
- (void)didReceiveAgreedFromUsername:(NSString *)aUsername
{
    NSLog(@"%@同意了我的好友請求",aUsername);
    
    [self getFridendListAndReloadTableView];//獲取好友列表并刷新tableView
}
- (void)didReceiveDeclinedFromUsername:(NSString *)aUsername
{
    NSLog(@"%@拒絕了我的好友請求",aUsername);
}

#pragma mark -
- (IBAction)exitAction:(UIBarButtonItem *)sender {
    
    //退出登錄
    EMError *error = [[EMClient sharedClient] logout:YES];
    if (!error) {
        NSLog(@"退出成功");
        [self dismissViewControllerAnimated:YES completion:^{
        }];
    }else{
        NSLog(@"退出失敗");
    }
    
}

#pragma mark - Table view data source

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return _nameArr.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    FriendListTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FriendListTableViewCell" forIndexPath:indexPath];
    
    NSString* username=_nameArr[indexPath.row];
    cell.nameLabel.text=username;
    
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//    //創(chuàng)建聊天會話,傳遞用戶或群id和會話類型(EMConversationType)
//    EaseMessageViewController *chatController = [[EaseMessageViewController alloc] initWithConversationChatter:_nameArr[indexPath.row] conversationType:EMConversationTypeChat];
//    chatController.title=_nameArr[indexPath.row];
//    [self.navigationController pushViewController:chatController animated:YES];

    
    //創(chuàng)建聊天會話,傳遞用戶或群id和會話類型(EMConversationType)
    ChatViewController *chatController = [[ChatViewController alloc] initWithConversationChatter:_nameArr[indexPath.row] conversationType:EMConversationTypeChat];
    chatController.title=_nameArr[indexPath.row];
    [self.navigationController pushViewController:chatController animated:YES];

}
  • 獲取好友列表
EMError *error = nil; NSArray *userlist = [[EMClient sharedClient].contactManager getContactsFromServerWithError:&error];
  • 好友申請
  • 發(fā)送加好友申請
    如果您已經發(fā)過,并且對方沒有處理招刨,您將不能再次發(fā)送
EMError *error = [[EMClient sharedClient].contactManager addContact:@"6001" message:@"我想加您為好友"];
if (!error) { NSLog(@"添加成功");}
  • 監(jiān)聽加好友請求
    當您收到好友請求霎俩,如果您沒有處理,請自己保存數據沉眶,新協議下不會每次都發(fā)送
//注冊好友回調
[[EMClient sharedClient].contactManager addDelegate:self delegateQueue:nil];
//移除好友回調
[[EMClient sharedClient].contactManager removeDelegate:self];
  • 監(jiān)聽回調
用戶A發(fā)送加用戶B為好友的申請打却,用戶B會收到這個回調 
aUsername 用戶名 
aMessage 附屬信息
-(void)didReceiveFriendInvitationFromUsername:(NSString *)aUsername message:(NSString *)aMessage;
  • 同意加好友申請
EMError *error = [[EMClient sharedClient].contactManager acceptInvitationForUsername:@"8001"];
if (!error) { NSLog(@"發(fā)送同意成功");}
  • 拒絕加好友申請
EMError *error = [[EMClient sharedClient].contactManager declineInvitationForUsername:@"8001"];
if (!error) { NSLog(@"發(fā)送拒絕成功");}
  • 好友申請?zhí)幚斫Y果回調
    監(jiān)聽回調
用戶A發(fā)送加用戶B為好友的申請,用戶B同意后谎倔,用戶A會收到這個回調
-(void)didReceiveAgreedFromUsername:(NSString *)aUsername;
用戶A發(fā)送加用戶B為好友的申請柳击,用戶B拒絕后,用戶A會收到這個回調
-(void)didReceiveDeclinedFromUsername:(NSString *)aUsername;
  • 退出登錄
EMError *error = [[EMClient sharedClient] logout:YES];
if (!error) { NSLog(@"退出成功");}
  • 大家可能注意到了片习,我導入了這2個文件
#import "EaseMessageViewController.h"http://單聊基礎界面
#import "ChatViewController.h"http://單聊chat界面

這2個控制器都是環(huán)信提供給我們的單聊控制器,EaseMessageViewController這是基礎的控制器捌肴,如果我們想要使用這個控制器蹬叭,但又覺得這個控制器滿足不了我們的要求的話,我們有2個辦法状知。1.使用ChatViewController 2.我們可以仿照ChatViewController寫一個繼承EaseMessageViewController的控制器秽五。
如果你對控制器有更高定制要求的話,可以根據文檔來自己實現相應的功能饥悴,而不局限于EaseMessageViewController

注意

  • 有一個bug坦喘,用模擬器播放錄音會崩潰,在手機上播放就沒問題
  • 環(huán)信不會保存我們的頭像西设,所以我們可以從app服務器獲取頭像
  • 比如我們使用的是ChatViewController起宽,我們可以在ChatViewController.m文件的EaseMessageViewControllerDataSource中的
-(id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
                           modelForMessage:(EMMessage *)message
{
}

中來改變頭像

-(id<IMessageModel>)messageViewController:(EaseMessageViewController *)viewController
                           modelForMessage:(EMMessage *)message
{
    id<IMessageModel> model = nil;
    model = [[EaseMessageModel alloc] initWithMessage:message];
 
    if (model.isSender) {//自己的頭像 昵稱
        model.avatarImage=[UIImage imageNamed:@"蠟筆小新.jpg"];
        model.nickname=@"我";
    }else{
        model.avatarImage=[UIImage imageNamed:@"美女.jpg"];
    }
  
    model.failImageName = @"imageDownloadFail";
    return model;
}

我們可以通過model.avatarURLPath=@""來從網絡獲取頭像
也可以通過model.avatarImage來改變頭像

  • 改變氣泡,還是拿ChatViewController舉例济榨,我們可以在ChatViewController.mviewDidLoad中,改變此處的圖片名稱
    [[EaseBaseMessageCell appearance] setSendBubbleBackgroundImage:[[UIImage imageNamed:@"chat_sender_bg"] stretchableImageWithLeftCapWidth:5 topCapHeight:35]];
    [[EaseBaseMessageCell appearance] setRecvBubbleBackgroundImage:[[UIImage imageNamed:@"chat_receiver_bg"] stretchableImageWithLeftCapWidth:35 topCapHeight:35]];
這樣我們就簡單的集成了3.x的單聊,在此點擊下載Demo

界面在Main.storyboard中,選中左側一列绿映。



注:相關內容我會繼續(xù)更新擒滑。如果想找一些iOS方面的代碼可以關注我的簡書,我會持續(xù)更新叉弦,大家一起探討探討
在此謝謝大家閱讀

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末丐一,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子淹冰,更是在濱河造成了極大的恐慌库车,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件樱拴,死亡現場離奇詭異柠衍,居然都是意外死亡,警方通過查閱死者的電腦和手機晶乔,發(fā)現死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門珍坊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人正罢,你說我怎么就攤上這事阵漏。” “怎么了翻具?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵履怯,是天一觀的道長。 經常有香客問我裆泳,道長叹洲,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任工禾,我火速辦了婚禮疹味,結果婚禮上仅叫,老公的妹妹穿的比我還像新娘。我一直安慰自己糙捺,他們只是感情好诫咱,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著洪灯,像睡著了一般坎缭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上签钩,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天掏呼,我揣著相機與錄音,去河邊找鬼铅檩。 笑死憎夷,一個胖子當著我的面吹牛,可吹牛的內容都是我干的昧旨。 我是一名探鬼主播拾给,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼兔沃!你這毒婦竟也來了蒋得?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤乒疏,失蹤者是張志新(化名)和其女友劉穎额衙,沒想到半個月后,有當地人在樹林里發(fā)現了一具尸體怕吴,經...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡窍侧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現自己被綠了转绷。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疏之。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖暇咆,靈堂內的尸體忽然破棺而出锋爪,到底是詐尸還是另有隱情,我是刑警寧澤爸业,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布其骄,位于F島的核電站,受9級特大地震影響扯旷,放射性物質發(fā)生泄漏拯爽。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一钧忽、第九天 我趴在偏房一處隱蔽的房頂上張望毯炮。 院中可真熱鬧逼肯,春花似錦、人聲如沸桃煎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽为迈。三九已至三椿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間葫辐,已是汗流浹背搜锰。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留耿战,地道東北人蛋叼。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像剂陡,于是被迫代替她去往敵國和親狈涮。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容