LeanCloud實時通信模塊iOS端快速接入指南(二)

2016年03月03日更新

使用id A進入聊天,然后返回登陸界面使用id B進入聊天,然后對A發起會話會導致崩潰,原因是沒有關閉A的客戶端,會導致自己和自己發起會話。解決方法是在開啟聊天客戶端之前先關閉之前的客戶端,即改寫『登陸』的事件為下列代碼
- (IBAction)loginBtnClicked:(id)sender {
[[CDChatManager manager]closeWithCallback:^(BOOL succeeded, NSError *error) {
[[CDChatManager manager]openWithClientId:_textField.text callback:^(BOOL succeeded, NSError *error) {
ChatListViewController * chatList = [[ChatListViewController alloc]init];
[self.navigationController pushViewController:chatList animated:YES];
}];

 }];

}

寫在最前面

更新了最新版的LeanCloud的SDK
靜態庫的體積確實小了很多,但是有一些LeanCloud改了一小部分方法的名稱
如果按照我的攻略發現代碼有問題的,請把所有的Conv改為Conversation不管這個Conv是在開頭還是結尾還是方法名中間

比如老版的是

  [[CDChatManager manager] fetchConvWithOtherId:_textField.text callback:^(AVIMConversation *conversation, NSError *error) {
    }];

現在就是

[[CDChatManager manager]fetchConversationWithOtherId:@"78" callback:^(AVIMConversation *conversation, NSError *error) {
    }];

其他方法同上,如有其它發現我都會寫在這里
另外老版的CDUserModel協議已經更名為CDUserModelDelegate

  • LeanCloud的程序員一定是強迫癥晚期(╯‵□′)╯︵┻━┻

寫在前面

首先附上之前文章的鏈接
[LeanCloud實時通信模塊IOS端快速接入指南(一)]
廢話少說,這一節我們來實現一個相對完整的聊天功能。


功能描述

還記得上一節說過的LeanCloud如何創建聊天嗎?沒錯,你自己的id加上你要聊天的人的id就可以創建一個對話。
那么我們今天做這么一個東西,項目啟動時輸入一個自己的id,確認后彈出類似QQ的最近聊天界面,點擊最近聊天的任意會話進行聊天或對任意指定id發起聊天。

正文

準備項目

新建一個項目,起一個你喜歡的名字


初始化項目

然后是導入SDK,在AppDelegate中注冊,和前邊一樣


Paste_Image.png
搭建頁面結構

這里我們準備的項目在下一節還要繼續用,所以我們使用StoryBoard搭建一個相對完整的項目

*為了盡量照顧大多數人,我這里把構建StoryBoard的過程也貼出來,已經熟練使用的請忽略

刪除自帶的ViewController和Main.storyboard中對應的控件
在Main.storyboard中添加一個標簽欄控制器(TabBarViewController)并設置為根視圖控制器(勾選Is Initial View Controller選項,被設置為根視圖控制器的控件左邊會有箭頭)

設置標簽欄

去掉標簽欄自帶的兩個視圖控制器,更換成導航視圖控制器(NavigationController)
按住鼠標左鍵不動從標簽欄拖動到導航欄


添加關聯

松開鼠標后選擇ViewControlers

添加關聯

另一個導航欄一樣照做
運行項目,如下圖所示

Paste_Image.png
搭建登陸界面

前一篇說過,我們使用[CDChatManager manager] openWithClientId:@"Tom" callback:^(BOOL succeeded, NSError *error) {}];方法只需要一個自定義的ClientId就可以登陸一個聊天客戶端
因此第一個界面我們就用來輸入這個Id。
由于在StoryBoard中導航欄自帶的根視圖控制器默認是UITableVIewController,所以我們刪掉它,換成普通的視圖控制器
并給它一個標題--『登陸』

登陸界面

登陸界面很簡單,如下所示

Paste_Image.png

新建一個視圖控制器并將其和StroyBoard中的登陸界面關聯起來

Paste_Image.png
實現聊天

給登陸按鈕添加事件之前我們先創建接下來要跳轉的界面--最近聊天列表ChatListViewController,繼承于CDChatListVC

Paste_Image.png

在LoginViewController中引入頭文件
#import <CDChatManager.h>
#import"ChatListViewController.h"
按鈕的點擊事件這么寫
- (IBAction)loginBtnClicked:(id)sender {
[[CDChatManager manager]openWithClientId:_textField.text callback:^(BOOL succeeded, NSError *error) {
ChatListViewController * chatList = [[ChatListViewController alloc]init];
[self.navigationController pushViewController:chatList animated:YES];
}];
}

  • 這里解釋一下這個CDChatListVC,和前一篇用到的CDChatRoomVC一樣,這也是LeanChatLib中寫好的一個類,繼承于UITableVIewController,每個cell代表一個會話,第一次進入或者刷新會拉取最近的會話,獲取到一個叫做conversations的數組,然后將conversation作為數據源讀出每一個會話然后展示。點擊會話則進入聊天。我們將在下一節詳細講解他的方法并按照我們的需求加以改造,所以這里我們只需要先知道它是干嘛的就夠了。

剛才說了,這個ChatListViewController是一個UITableVIewController,所以我們對它稍加改造,給它的TableView加一個HeaderView。
在它的viewDidLoad中這么寫
- (void)viewDidLoad {
[super viewDidLoad];

UIView * headerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.width, 60)];
self.tableView.tableHeaderView = headerView;

_textField = [[UITextField alloc]initWithFrame:CGRectMake(15, 5, self.view.bounds.size.width - 30, 25)];
_textField.layer.borderColor = [UIColor lightGrayColor].CGColor;
_textField.layer.borderWidth = 1;
[headerView addSubview:_textField];

UIButton * startChat = [UIButton buttonWithType:UIButtonTypeSystem];
startChat.frame = CGRectMake(60, 35, self.view.bounds.size.width - 120, 20);
[startChat setTitle:@"開始聊天" forState:UIControlStateNormal];
[headerView addSubview:startChat];
[startChat addTarget:self action:@selector(startChatClicked:) forControlEvents:UIControlEventTouchUpInside];

}

在添加按鈕的點擊事件之前我們要向之前一樣,去創建一個繼承于CDChatRoomVC的ChatRoomViewController。

創建聊天室

把聊天室引入到聊天列表
#import "ChatRoomViewController.h"
然后是按鈕的點擊事件
- (void)startChatClicked:(UIButton *)btn
{
if(_textField.text.length > 0)
{
[[CDChatManager manager] fetchConvWithOtherId:_textField.text callback:^(AVIMConversation *conversation, NSError *error) {
ChatRoomViewController * chatRoom = [[ChatRoomViewController alloc]initWithConv:conversation];
[self.navigationController pushViewController:chatRoom animated:YES];
}];
}

}

因為標簽欄會遮住聊天室下方的輸入控件,所以我們這么做
在ChatListViewController中添加方法
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.tabBarController.tabBar.hidden = NO;
}
在ChatRoomViewController中添加方法
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.navigationController.tabBarController.tabBar.hidden = YES;
}

到此為止我們已經實現了前面的需求,運行項目
在登錄界面輸入你的id

登陸

點擊登陸后輸入你想聊天的人的id,然后點擊開始聊天

尋找聊天對象

出現如下界面

聊天界面

點擊返回

返回最近聊天列表

然后你會發現,臥槽?說好的最近聊天呢? 怎么一篇空白?別急,接下來我們就解決這個問題。

顯示最近聊天

剛才點返回的時候,控制臺會給你報一堆警告

控制臺警告

前面說過,你第一次進入最近聊天頁或者刷新最近聊天的時候會拉取到最近的會話,但是你拉取的是會話,和你聊天的對象的頭像昵稱等信息并沒有包含在會話對象中,你需要從CDChatManager的代理中獲取到這些信息。因此我們需要實現CDChatManager的CDUserDelegate。這個代理會返回一個遵循CDUserModel協議的對象。

創建一個繼承于NSObject的UserFactory類

UserFactory

引入頭文件
#import <LeanChatLib/LeanChatLib.h>
遵守協議

@interface UserFactory : NSObject <CDUserDelegate>

@end

在UserFactory.m中實現代理方法
為了方便我們把遵循CDUserModel協議的類也在這里聲明

#import "CDUserFactory.h"

@interface CDUser : NSObject <CDUserModel>

@property (nonatomic, strong) NSString *userId;

@property (nonatomic, strong) NSString *username;

@property (nonatomic, strong) NSString *avatarUrl;

@end

@implementation CDUser

@end

@implementation UserFactory

#pragma mark - UserDelegate


- (void)cacheUserByIds:(NSSet *)userIds block:    (AVBooleanResultBlock)block {
block(YES, nil); 
}

- (id <CDUserModel> )getUserById:(NSString *)userId {
CDUser *user = [[CDUser alloc] init];
user.userId = userId;
//在cell中顯示的聊天對象的名字
user.username = userId;
//聊天對象的頭像
user.avatarUrl = @"http://tp2.sinaimg.cn/5088940253/180/5745995456/1";
return user;
}

@end

然后在Appdelegate.m中添加代理
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
[CDChatManager manager].userDelegate = [[UserFactory alloc]init];
...
return YES;
}

然后再次運行項目,輸入剛才的ID,這個時候我們的最近聊天列表就出現了

成功
  • 頭像不顯示的同學請檢查是否打開了ATS。iOS 9 之后默認開啟ATS,無法使用Http請求
    關閉方法為在info.plist中添加字段
    <key>NSAppTransportSecurity</key>
    <dict>
    <key>NSAllowsArbitraryLoads</key>
    <true/>
    </dict>

接下來我們要做的是實現點擊最近會話進入聊天
首先讓ChatListViewController遵循協議
interface ChatListViewController ()<CDChatListVCDelegate>

然后在viewDidLoad方法中添加加上一句
self.chatListDelegate = self;

然后實現代理方法
- (void)viewController:(UIViewController *)viewController didSelectConv:(AVIMConversation *)conv
{
ChatRoomViewController * chatRoom = [[ChatRoomViewController alloc]initWithConv:conv];
[self.navigationController pushViewController:chatRoom animated:YES];
}
再運行試試,點擊最近的聊天也可以進入聊天了


總結

到此為止,我們就利用LeanCloud搭建了一個相對完整的聊天,你已經可以用這個東西跟你的小伙伴聊天了。
雖然我寫了這么多亂七八糟的東西,其實總計一下我們只用了三個類就實現了這全部的東西。
這里我們回顧一下

三個類:
  • CDChatRoomVC:LeanChatLib提供的聊天室。擁有帶Conversation參數的構造方法,聲明后直接跳轉進來即可。
  • CDChatListVC:LeanChatLib提供的聊天列表類,登陸聊天Client后直接跳轉進入或者進入后再登陸Client都可以。
  • CDChatManager:LeanChatLib的核心管理類,通過[CDChatManager manager]獲取單例。它的兩個重要方法:
    //登陸一個聊天客戶端 openWithClientId:_textField.text callback:^(BOOL succeeded, NSError *error) { };
    //獲取一個單聊會話 fetchConvWithOtherId:@"78" callback:^(AVIMConversation *conversation, NSError *error) { }

為了方便理解,這里再多嘴提一句,第一個方法,openClientId。既然有open,對應的也有一個close方法用來關閉聊天客戶端。我們所開啟的這個Client,不像我們學的Button,Label一樣,依附于父視圖,父視圖銷毀,它們也跟著銷毀。Client除非你主動關閉或者直接關掉程序,執行open之后它會一直在后臺處于開啟狀態。這也就意味著,只要你執行了openClient,你可以在程序的任意一個界面執行fetchConv獲取到一個會話然后跳轉到聊天,并不一定是在最近聊天列表才能這么做。這樣就能很方便靈活的使用即時通訊模塊。


這一節到此結束,下一節,我們來學習按照自己的需求改造我們的聊天功能。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,119評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,382評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 176,038評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,853評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,616評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,112評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,192評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,355評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,869評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,727評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,928評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,467評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,165評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,570評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,813評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,585評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,892評論 2 372

推薦閱讀更多精彩內容