?1.1:融云的分類(簡(jiǎn)介)
1.1.1:融云 IM 界面組件 - RongCloud IMKit
IMKit 是融云 SDK 的核心特色之一倾贰。融云將即時(shí)通訊產(chǎn)品中最復(fù)雜的會(huì)話列表鸿竖、聊天窗口全跨、消息內(nèi)容展現(xiàn)湃窍、會(huì)話設(shè)置等功能封裝為組件姑食,通過(guò)簡(jiǎn)短的代碼,就可以直接將以上界面集成到App 產(chǎn)品中荐健,省去大量的開發(fā)調(diào)試時(shí)間酱畅。融云同時(shí)支持業(yè)內(nèi)最豐富的自定義界面組件功能,我們可以針對(duì)自己界面需求自由設(shè)計(jì)開發(fā)江场。
1.1.2:融云 IM 通訊能力庫(kù) - RongCloud IMLib
IMLib 是不含界面的基礎(chǔ) IM 通訊能力庫(kù)纺酸,封裝了通信能力和會(huì)話、消息等對(duì)象址否。引用到 App 工程中后餐蔬,需要自己實(shí)現(xiàn) UI 界面,相對(duì)較輕量佑附,適用于對(duì) UI 有較高訂制需求的開發(fā)者樊诺。
1.1.3:融云 Call 界面組件 - RongCloud CallKit
CallKit 是融云音視頻通話功能的 UI 界面 SDK。(基于RongCloud CallLib)包含了單人音同、多人音視頻通話的界面的各種場(chǎng)景和功能词爬。可以快速的集成 CallKit 來(lái)實(shí)現(xiàn)豐富的音視頻通話界面权均,并進(jìn)行 UI 定制開發(fā)顿膨。同時(shí)開源了 CallKit,您可以根據(jù)您的需要去使用叽赊。
1.1.4:融云 Call 通訊能力庫(kù) - RongCloud CallLib
1.2:融云 SDK的導(dǎo)入
1.2.1:通過(guò) CocoaPods 導(dǎo)入管理依賴庫(kù)(一般建議選用這個(gè)恋沃,不用手動(dòng)管理依賴庫(kù),并且升級(jí)方便)
1.2.2:手動(dòng)導(dǎo)入 SDK 并自己管理依賴庫(kù)
1.3:融云的登錄
1.3.1:登錄方式: appKey? 從融云開發(fā)者平臺(tái)創(chuàng)建應(yīng)用后獲取到的App Key必指,這個(gè)App Key必須和服務(wù)端保持一致芽唇。不然下面的token驗(yàn)證通不過(guò)。
[[RCIM sharedRCIM] initWithAppKey:RONGCLOUNDAPP_KEY]; //初始化融云SDK取劫,在APP初始化的時(shí)候必須走這個(gè)方法匆笤。
1.3.2:登錄方法:Token令牌登錄方式 注:token是從我們自己服務(wù)器獲取(屬于服務(wù)與融云的交互)
[[RCIM sharedRCIM] connectWithToken:loginModel.RongCloudToken success:^(NSString *userId) {
? ? ?} error:^(RCConnectErrorCode status) {
? ? ? ? ?NSLog(@"登陸的錯(cuò)誤碼為:%ld", (long)status);
? ? } tokenIncorrect:^{
? ? ? ? NSLog(@"token錯(cuò)誤");
? ? }];
1.3.3 :登錄前所需做的事情(主要是RCIM 這個(gè)單例類的一些方法 用來(lái)設(shè)置一些全局變量)
//全局的導(dǎo)航按鈕字體顏色
[RCIM sharedRCIM].globalNavigationBarTintColor = [UIColor blackColor];
//聊天界面中顯示的頭像大小
'[RCIM sharedRCIM].globalMessagePortraitSize = CGSizeMake(46, 46);
?[RCIM sharedRCIM].globalMessageAvatarStyle = RC_USER_AVATAR_CYCLE;
//聊天界面中顯示的頭像形狀谱邪,矩形或者圓形
?[RCIM sharedRCIM].globalConversationAvatarStyle=RC_USER_AVATAR_CYCLE;
//設(shè)置接收消息代理
?[RCIM sharedRCIM].receiveMessageDelegate=self;
? [RCIM sharedRCIM].userInfoDataSource=self;
//設(shè)置IMKit連接狀態(tài)的監(jiān)聽器
[RCIM sharedRCIM].connectionStatusDelegate=self;
?1.4:簡(jiǎn)單實(shí)現(xiàn)聊天功能(不涉及業(yè)務(wù)邏輯和產(chǎn)品需求)
1.4.1:繼承或者啟動(dòng)RCConversationListViewController這個(gè)控制器就可以打開聊天列表
?//創(chuàng)建試圖 直接跳轉(zhuǎn)
?WMConversationListViewController *recommendNewVC=[[WMConversationListViewController alloc]init];
? ? ? ? ? ? //recommendNewVC.xiaoxilx=model.XIAOXILX;
? ? ? ? ? ? ?[self.navigationController showViewController:recommendNewVC sender:nil];
?//在試圖初始化的時(shí)候 設(shè)置在列表中需要顯示的會(huì)話類型 (微脈項(xiàng)目只有單聊)
? ? ?[self setDisplayConversationTypes:@[@(ConversationType_PRIVATE),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@(ConversationType_DISCUSSION),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@(ConversationType_CHATROOM),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@(ConversationType_GROUP),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@(ConversationType_APPSERVICE),
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?@(ConversationType_SYSTEM)]];
1.4.2:繼承或者啟動(dòng) RCConversationViewController這個(gè)頁(yè)面就可以打開聊天頁(yè)面
//新建一個(gè)聊天會(huì)話View Controller對(duì)象
RCConversationViewController *chat = [[RCConversationViewController alloc]init];
?//設(shè)置會(huì)話的類型炮捧,如單聊、討論組惦银、群聊咆课、聊天室、客服扯俱、公眾服務(wù)會(huì)話等
?chat.conversationType = ConversationType_PRIVATE;
//設(shè)置會(huì)話的目標(biāo)會(huì)話ID书蚪。(單聊、客服迅栅、公眾服務(wù)會(huì)話為對(duì)方的ID殊校,討論組、群聊读存、聊天室為會(huì)話的ID)
?chat.targetId = @"targetIdYouWillChatIn";
?//設(shè)置聊天會(huì)話界面要顯示的標(biāo)題
?chat.title = @"想顯示的會(huì)話標(biāo)題";
?//顯示聊天會(huì)話界面
?[self.navigationController pushViewController:chat animated:YES];
總結(jié):到這里截止为流,我們就可以實(shí)現(xiàn)單純意義上的實(shí)現(xiàn)聊天功能呕屎。
?2:融云集成進(jìn)階
?2.1 :遺留問(wèn)題
在第一個(gè)階段聊天的時(shí)候,你會(huì)發(fā)現(xiàn)在聊天列表界面只能顯示出未讀消息和未讀消息的數(shù)目以及時(shí)間敬察。聊天人的姓名和頭像卻是看不見(jiàn)的秀睛。
原因是因?yàn)椋喝谠票旧碜鳛镮M實(shí)現(xiàn)的工具,不做這些數(shù)據(jù)的傳輸和保存(猜測(cè):1莲祸,畢竟需要耗流量蹂安,能省則省。2锐帜,不參與到app邏輯藤抡,需求太多滿足不了)。所以這兩個(gè)基本數(shù)據(jù)的存儲(chǔ)抹估,展示和跟新落就理所當(dāng)然的落到了我們APP自己身上(包括后期產(chǎn)品需要自定義UI數(shù)據(jù)的展示 ,—后面這個(gè)問(wèn)題涉及到自定義聊天列表了弄兜,不在這里討論了)药蜻。
2.2:解決方案
上面問(wèn)題的根源是頭像和姓名這些數(shù)據(jù)從哪里來(lái)? 顯然必須用接口從我們自己服務(wù)器去獲取 替饿,但是考慮到不能頻繁請(qǐng)求接口調(diào)相同數(shù)據(jù) 语泽,所以APP必須建立數(shù)據(jù)庫(kù),把基本信息存儲(chǔ)到本地视卢。為了方便管理和增加可讀性踱卵,在項(xiàng)目中我創(chuàng)建WMRCDataManager文件來(lái)管理 數(shù)據(jù)存儲(chǔ)問(wèn)題。(其實(shí)融云本地是做了自己的數(shù)據(jù)庫(kù)据过,但是不提供給給我們方法惋砂。)
單例類的創(chuàng)建
+(WMRCDataManager *) shareManager;
?//userInfoDataSource的代理回調(diào)
- (void)getUserInfoWithUserId:(NSString*)userId completion:(void (^)(RCUserInfo*))completion;
微脈數(shù)據(jù)存儲(chǔ)機(jī)制如圖:
?2.3:延伸新問(wèn)題
這樣做的弊端:如果對(duì)方刷新信息,而前端已經(jīng)緩存了消息绳锅,此時(shí)不會(huì)再次網(wǎng)絡(luò)請(qǐng)求西饵,導(dǎo)致數(shù)據(jù)跟新不及時(shí)。
解決方案:根據(jù)研究QQ和微信發(fā)現(xiàn)他們的數(shù)據(jù)跟新是在進(jìn)入聊天頁(yè)面或者查看他們的信息的時(shí)候鳞芙。所以暫定解決辦法是眷柔,在每一次進(jìn)入聊天頁(yè)面時(shí)候獲取一下對(duì)方最新信息。然后跟新本地?cái)?shù)據(jù)庫(kù)數(shù)據(jù)原朝。(弊端:調(diào)用接口的次數(shù)還是很多驯嘱。從性能上講不合理。不過(guò)我們的產(chǎn)品暫時(shí)沒(méi)有這方面的需求喳坠,所以沒(méi)做)
3:聊天列表UI和聊天UI的自定義
前言:每一個(gè)產(chǎn)品都有一個(gè)自己風(fēng)格和需求鞠评,所以融云的聊天列表的UI和聊天詳情的UI基本上滿足不了微脈的需求。這里自定義UI的實(shí)現(xiàn)就很有必要了壕鹉。
?3.1:聊天列表的UI的自定義
3.1.1:我們項(xiàng)目中聊天列表WMConversationListViewController 是在繼承RCConversationListViewController視圖的基礎(chǔ)上創(chuàng)建的谢澈。這里有可能你會(huì)問(wèn):為什么不自己寫一個(gè)界面煌贴,不集成他們的界面?原因如下:雖然我們的視圖展示改變了锥忿,但是依然需要使用這個(gè)界面的刷新邏輯(相對(duì)而言牛郑,工作量小,效率高)敬鬓。
自定義列表cell需要調(diào)用下面四個(gè)方法
?即將加載列表數(shù)據(jù)源的回調(diào)淹朋,這個(gè)方法很必要是一個(gè)轉(zhuǎn)換數(shù)據(jù)類型的功能,起橋接作用
@param dataSource? 即將加載的列表數(shù)據(jù)源(元素為RCConversationModel對(duì)象)
@return? ? ? ? 修改后的數(shù)據(jù)源(元素為RCConversationModel對(duì)象)
@discussion 您可以在回調(diào)中修改钉答、添加础芍、刪除數(shù)據(jù)源的元素來(lái)定制顯示的內(nèi)容,會(huì)話列表會(huì)根據(jù)您返回的修改后的數(shù)據(jù)源進(jìn)行顯示数尿。
數(shù)據(jù)源中存放的元素為會(huì)話Cell的數(shù)據(jù)模型仑性,即RCConversationModel對(duì)象。
-(NSMutableArray *)willReloadTableData:(NSMutableArray *)dataSource{
for (int i=0; i<dataSource.count ; i++){
RCConversationModel *model = dataSource[i];
if(model.conversationType == ConversationType_PRIVATE){
// 會(huì)話Cell數(shù)據(jù)模型的顯示類型 轉(zhuǎn)化為自定義類型
model.conversationModelType = RC_CONVERSATION_MODEL_TYPE_CUSTOMIZATION;
}
}
return dataSource;
}
自定義會(huì)話Cell顯示時(shí)的回調(diào)
-(RCConversationBaseCell *)rcConversationListTableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
//拿到數(shù)據(jù)源
RCConversationModel *model = self.conversationListDataSource[indexPath.row];
//注冊(cè)cell
WMRCChatListCell *cell = (WMRCChatListCell *)[[WMRCChatListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"WMRCChatListCell"];
//中間cell上控件的賦值這里省略
return cell;
}
自定義會(huì)話Cell顯示時(shí)的回調(diào)
-(CGFloat)rcConversationListTableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
//返回cell高度
return kCellHeight;
}
左滑刪除自定義會(huì)話時(shí)的回調(diào)
- (void)rcConversationListTableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath {
'[[RCIMClient sharedRCIMClient] removeConversation:model.conversationType targetId:model.targetId];
''? [[RCIMClient sharedRCIMClient]clearMessages:ConversationType_PRIVATE targetId:model.targetId];
}
3.1.2:第一個(gè)方法很關(guān)鍵右蹦。他是一個(gè)轉(zhuǎn)換的功能诊杆,可以把指定的一類消息轉(zhuǎn)換為自定義消息類型。例如:把單聊類型轉(zhuǎn)化為自定義類型何陆。
3.1.3:然后在cellForRowAtIndexPath方法中直接,創(chuàng)建cell晨汹。然后給cell上的控件賦值。(這里的數(shù)據(jù)從哪里來(lái)贷盲?)這個(gè)時(shí)候就開始調(diào)用WMRCDataManager 類的getUserInfoWithUserId這個(gè)方法從本地獲取數(shù)據(jù)淘这,(這里本地如果沒(méi)有數(shù)據(jù),我會(huì)從服務(wù)接口去拿巩剖,然后緩存到本地铝穷,這樣就不用么一次都調(diào)用接口,給服務(wù)端怎成壓力了佳魔。)
WMRCChatListCell *cell = (WMRCChatListCell *)[[WMRCChatListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"WMRCChatListCell"];
3.1.4:數(shù)據(jù)展示完了氧骤,我們直接調(diào)用heightForRowAtIndexPath的方法把cell的高展示出來(lái)。
3.1.5:commitEditingStyle用來(lái)左滑刪除單個(gè)會(huì)話列表的吃引,這里有兩種刪除意思:1:從列表中刪除這個(gè)記錄筹陵,但是聊天消息并不刪除依然在本地存儲(chǔ)。
2:列表刪除并把聊天記錄一并刪除镊尺。
[[RCIMClient sharedRCIMClient] removeConversation:model.conversationType targetId:model.targetId];
[[RCIMClient sharedRCIMClient]clearMessages:ConversationType_PRIVATE targetId:model.targetId];
自此自定義聊天列表已經(jīng)按照要求滿足我們微脈的需求朦佩。
3.2:聊天頁(yè)面UI的自定義
這一塊項(xiàng)目上暫時(shí)還未實(shí)現(xiàn)。私下已經(jīng)走通了簡(jiǎn)單消息的自定義庐氮。
3.2.1自定義消息類—WMRCRichMessage 必須繼承與RCMessageContent 语稠。這樣這一條消息才會(huì)儲(chǔ)并計(jì)入未讀消息數(shù)。
//聲明一個(gè)標(biāo)志
#define? ? WMRCRichMessageTypeIdentifier @"RCD:WMRichMsg"
3.2.2 在融云注冊(cè)之前先注冊(cè)消息類型(申明此類的存在)
// 注冊(cè)自定義測(cè)試消息 是消息類型
//RCDTestMessage
?[[RCIM sharedRCIM] registerMessageType:[RCDTestMessage class]];
3.2.3自定義cell—WMRCRichMessageCell 必須繼承與RCMessageCell 。這樣這cell才能展示用戶信息和內(nèi)容的消息仙畦。而且這類cell在注冊(cè)時(shí)候必須和RCDTestMessage消息進(jìn)行綁定输涕。如下:
[self registerClass:[RCDTestMessageCell class] forCellWithReuseIdentifier:RCDTestMessageTypeIdentifier];
3.2.4參照聊天列表頁(yè)面UI的自定義 實(shí)現(xiàn)以下三個(gè)方法
注冊(cè)自定義消息的Cell
@param cellClass? 自定義消息的類,該自定義消息需要繼承于RCMessageContent
@param identifier? 自定義消息Cell的唯一標(biāo)示符
@discussion 聊天界面在顯示時(shí)需要通過(guò)identifier唯一標(biāo)示來(lái)進(jìn)行Cell重用慨畸,以提高性能莱坎。
我們建議您在identifier中添加前綴,請(qǐng)勿使用"rc"前綴的字符串寸士,以免與融云內(nèi)置消息的Cell沖突檐什。
- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;
自定義消息Cell顯示的回調(diào)
@param collectionView? 當(dāng)前CollectionView
@param indexPath? ? ? 該Cell對(duì)應(yīng)的消息Cell數(shù)據(jù)模型在數(shù)據(jù)源中的索引值
@return? ? ? ? ? ? ? ? 自定義消息需要顯示的Cell
@discussion 自定義消息如果需要顯示,則必須先通過(guò)RCIM的registerMessageType:注冊(cè)該自定義消息類型弱卡,
并在聊天界面中通過(guò)registerClass:forCellWithReuseIdentifier:注冊(cè)該自定義消息的Cell乃正,否則將此回調(diào)將不會(huì)被調(diào)用。
- (RCMessageBaseCell *)rcConversationCollectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath;
自定義消息Cell顯示的回調(diào)
@param collectionView? ? ? ? ? 當(dāng)前CollectionView
@param collectionViewLayout? ? 當(dāng)前CollectionView Layout
@param indexPath? ? ? ? ? ? ? 該Cell對(duì)應(yīng)的消息Cell數(shù)據(jù)模型在數(shù)據(jù)源中的索引值
@return? ? ? ? ? ? ? ? ? ? ? ? 自定義消息Cell需要顯示的高度
@discussion 自定義消息如果需要顯示婶博,則必須先通過(guò)RCIM的registerMessageType:注冊(cè)該自定義消息類型瓮具,
并在聊天界面中通過(guò)registerClass:forCellWithReuseIdentifier:注冊(cè)該自定義消息的Cell,否則將此回調(diào)將不會(huì)被調(diào)用凡人。
- (CGSize)rcConversationCollectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath;
4:總結(jié)
第三方接入名党,本身的難度有限,但是為了滿足產(chǎn)品的邏輯去修改第三方的本身邏輯是最蛋疼的事情划栓。解決問(wèn)題的關(guān)鍵是:看文檔,看官方demo条获,多嘗試忠荞。