IM 的集成

 1.1:融云的分类(简介)

1.1.1:融云 IM 界面组件 - RongCloud IMKit

IMKit 是融云 SDK 的核心特色之一。融云将即时通讯产品中最复杂的会话列表、聊天窗口、消息内容展现、会话设置等功能封装为组件,通过简短的代码,就可以直接将以上界面集成到App 产品中,省去大量的开发调试时间。融云同时支持业内最丰富的自定义界面组件功能,我们可以针对自己界面需求自由设计开发。

1.1.2:融云 IM 通讯能力库 - RongCloud IMLib

IMLib 是不含界面的基础 IM 通讯能力库,封装了通信能力和会话、消息等对象。引用到 App 工程中后,需要自己实现 UI 界面,相对较轻量,适用于对 UI 有较高订制需求的开发者。

1.1.3:融云 Call 界面组件 - RongCloud CallKit

CallKit 是融云音视频通话功能的 UI 界面 SDK。(基于RongCloud CallLib)包含了单人、多人音视频通话的界面的各种场景和功能。可以快速的集成 CallKit 来实现丰富的音视频通话界面,并进行 UI 定制开发。同时开源了 CallKit,您可以根据您的需要去使用。

1.1.4:融云 Call 通讯能力库 - RongCloud CallLib

1.2:融云 SDK的导入

1.2.1:通过 CocoaPods 导入管理依赖库(一般建议选用这个,不用手动管理依赖库,并且升级方便)

1.2.2:手动导入 SDK 并自己管理依赖库

1.3:融云的登录

1.3.1:登录方式: appKey  从融云开发者平台创建应用后获取到的App Key,这个App Key必须和服务端保持一致。不然下面的token验证通不过。

[[RCIM sharedRCIM] initWithAppKey:RONGCLOUNDAPP_KEY]; //初始化融云SDK,在APP初始化的时候必须走这个方法。

1.3.2:登录方法:Token令牌登录方式 注:token是从我们自己服务器获取(属于服务与融云的交互)

[[RCIM sharedRCIM] connectWithToken:loginModel.RongCloudToken success:^(NSString *userId) {

     } error:^(RCConnectErrorCode status) {

         NSLog(@"登陆的错误码为:%ld", (long)status);

    } tokenIncorrect:^{

        NSLog(@"token错误");

    }];

1.3.3 :登录前所需做的事情(主要是RCIM 这个单例类的一些方法 用来设置一些全局变量)

//全局的导航按钮字体颜色

[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;

//设置接收消息代理

 [RCIM sharedRCIM].receiveMessageDelegate=self;

  [RCIM sharedRCIM].userInfoDataSource=self;

//设置IMKit连接状态的监听器

[RCIM sharedRCIM].connectionStatusDelegate=self;

 1.4:简单实现聊天功能(不涉及业务逻辑和产品需求)

1.4.1:继承或者启动RCConversationListViewController这个控制器就可以打开聊天列表

 //创建试图 直接跳转

 WMConversationListViewController *recommendNewVC=[[WMConversationListViewController alloc]init];

            //recommendNewVC.xiaoxilx=model.XIAOXILX;

             [self.navigationController showViewController:recommendNewVC sender:nil];

 //在试图初始化的时候 设置在列表中需要显示的会话类型 (微脉项目只有单聊)

     [self setDisplayConversationTypes:@[@(ConversationType_PRIVATE),

                                       @(ConversationType_DISCUSSION),

                                         @(ConversationType_CHATROOM),

                                         @(ConversationType_GROUP),

                                         @(ConversationType_APPSERVICE),

                                         @(ConversationType_SYSTEM)]];

1.4.2:继承或者启动 RCConversationViewController这个页面就可以打开聊天页面

//新建一个聊天会话View Controller对象

RCConversationViewController *chat = [[RCConversationViewController alloc]init];

 //设置会话的类型,如单聊、讨论组、群聊、聊天室、客服、公众服务会话等

 chat.conversationType = ConversationType_PRIVATE;

//设置会话的目标会话ID。(单聊、客服、公众服务会话为对方的ID,讨论组、群聊、聊天室为会话的ID)

 chat.targetId = @"targetIdYouWillChatIn";

 //设置聊天会话界面要显示的标题

 chat.title = @"想显示的会话标题";

 //显示聊天会话界面

 [self.navigationController pushViewController:chat animated:YES];

总结:到这里截止,我们就可以实现单纯意义上的实现聊天功能。

 2:融云集成进阶

 2.1 :遗留问题

在第一个阶段聊天的时候,你会发现在聊天列表界面只能显示出未读消息和未读消息的数目以及时间。聊天人的姓名和头像却是看不见的。

原因是因为:融云本身作为IM实现的工具,不做这些数据的传输和保存(猜测:1,毕竟需要耗流量,能省则省。2,不参与到app逻辑,需求太多满足不了)。所以这两个基本数据的存储,展示和跟新落就理所当然的落到了我们APP自己身上(包括后期产品需要自定义UI数据的展示 ,—后面这个问题涉及到自定义聊天列表了,不在这里讨论了)。

2.2:解决方案

上面问题的根源是头像和姓名这些数据从哪里来? 显然必须用接口从我们自己服务器去获取 ,但是考虑到不能频繁请求接口调相同数据 ,所以APP必须建立数据库,把基本信息存储到本地。为了方便管理和增加可读性,在项目中我创建WMRCDataManager文件来管理 数据存储问题。(其实融云本地是做了自己的数据库,但是不提供给给我们方法。)

单例类的创建

+(WMRCDataManager *) shareManager;

 //userInfoDataSource的代理回调

- (void)getUserInfoWithUserId:(NSString*)userId completion:(void (^)(RCUserInfo*))completion;

微脉数据存储机制如图:

微脉数据存储机制图


 2.3:延伸新问题

这样做的弊端:如果对方刷新信息,而前端已经缓存了消息,此时不会再次网络请求,导致数据跟新不及时。

解决方案:根据研究QQ和微信发现他们的数据跟新是在进入聊天页面或者查看他们的信息的时候。所以暂定解决办法是,在每一次进入聊天页面时候获取一下对方最新信息。然后跟新本地数据库数据。(弊端:调用接口的次数还是很多。从性能上讲不合理。不过我们的产品暂时没有这方面的需求,所以没做)

3:聊天列表UI和聊天UI的自定义

前言:每一个产品都有一个自己风格和需求,所以融云的聊天列表的UI和聊天详情的UI基本上满足不了微脉的需求。这里自定义UI的实现就很有必要了。

 3.1:聊天列表的UI的自定义

3.1.1:我们项目中聊天列表WMConversationListViewController 是在继承RCConversationListViewController视图的基础上创建的。这里有可能你会问:为什么不自己写一个界面,不集成他们的界面?原因如下:虽然我们的视图展示改变了,但是依然需要使用这个界面的刷新逻辑(相对而言,工作量小,效率高)。

自定义列表cell需要调用下面四个方法

 即将加载列表数据源的回调,这个方法很必要是一个转换数据类型的功能,起桥接作用

@param dataSource  即将加载的列表数据源(元素为RCConversationModel对象)

@return        修改后的数据源(元素为RCConversationModel对象)

@discussion 您可以在回调中修改、添加、删除数据源的元素来定制显示的内容,会话列表会根据您返回的修改后的数据源进行显示。

数据源中存放的元素为会话Cell的数据模型,即RCConversationModel对象。

-(NSMutableArray *)willReloadTableData:(NSMutableArray *)dataSource{

for (int i=0; i<dataSource.count ; i++){

RCConversationModel *model = dataSource[i];

if(model.conversationType == ConversationType_PRIVATE){

// 会话Cell数据模型的显示类型 转化为自定义类型

model.conversationModelType = RC_CONVERSATION_MODEL_TYPE_CUSTOMIZATION;

}

}

return dataSource;

}


自定义会话Cell显示时的回调

-(RCConversationBaseCell *)rcConversationListTableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

//拿到数据源

RCConversationModel *model = self.conversationListDataSource[indexPath.row];

//注册cell

WMRCChatListCell *cell = (WMRCChatListCell *)[[WMRCChatListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"WMRCChatListCell"];

//中间cell上控件的赋值这里省略

return cell;

}

自定义会话Cell显示时的回调

-(CGFloat)rcConversationListTableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{

//返回cell高度

return kCellHeight;

}

左滑删除自定义会话时的回调

- (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:第一个方法很关键。他是一个转换的功能,可以把指定的一类消息转换为自定义消息类型。例如:把单聊类型转化为自定义类型。

3.1.3:然后在cellForRowAtIndexPath方法中直接,创建cell。然后给cell上的控件赋值。(这里的数据从哪里来?)这个时候就开始调用WMRCDataManager 类的getUserInfoWithUserId这个方法从本地获取数据,(这里本地如果没有数据,我会从服务接口去拿,然后缓存到本地,这样就不用么一次都调用接口,给服务端怎成压力了。)

WMRCChatListCell *cell = (WMRCChatListCell *)[[WMRCChatListCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"WMRCChatListCell"];

3.1.4:数据展示完了,我们直接调用heightForRowAtIndexPath的方法把cell的高展示出来。

3.1.5:commitEditingStyle用来左滑删除单个会话列表的,这里有两种删除意思:1:从列表中删除这个记录,但是聊天消息并不删除依然在本地存储。

2:列表删除并把聊天记录一并删除。

[[RCIMClient sharedRCIMClient] removeConversation:model.conversationType targetId:model.targetId];

[[RCIMClient sharedRCIMClient]clearMessages:ConversationType_PRIVATE targetId:model.targetId];

自此自定义聊天列表已经按照要求满足我们微脉的需求。

3.2:聊天页面UI的自定义

这一块项目上暂时还未实现。私下已经走通了简单消息的自定义。

3.2.1自定义消息类—WMRCRichMessage 必须继承与RCMessageContent 。这样这一条消息才会储并计入未读消息数。

//声明一个标志

#define    WMRCRichMessageTypeIdentifier @"RCD:WMRichMsg"

3.2.2 在融云注册之前先注册消息类型(申明此类的存在)

// 注册自定义测试消息 是消息类型

//RCDTestMessage

 [[RCIM sharedRCIM] registerMessageType:[RCDTestMessage class]];

3.2.3自定义cell—WMRCRichMessageCell 必须继承与RCMessageCell 。这样这cell才能展示用户信息和内容的消息。而且这类cell在注册时候必须和RCDTestMessage消息进行绑定。如下:

[self registerClass:[RCDTestMessageCell class] forCellWithReuseIdentifier:RCDTestMessageTypeIdentifier];

3.2.4参照聊天列表页面UI的自定义 实现以下三个方法

注册自定义消息的Cell

@param cellClass  自定义消息的类,该自定义消息需要继承于RCMessageContent

@param identifier  自定义消息Cell的唯一标示符

@discussion 聊天界面在显示时需要通过identifier唯一标示来进行Cell重用,以提高性能。

我们建议您在identifier中添加前缀,请勿使用"rc"前缀的字符串,以免与融云内置消息的Cell冲突。

- (void)registerClass:(Class)cellClass forCellWithReuseIdentifier:(NSString *)identifier;

自定义消息Cell显示的回调

@param collectionView  当前CollectionView

@param indexPath      该Cell对应的消息Cell数据模型在数据源中的索引值

@return                自定义消息需要显示的Cell

@discussion 自定义消息如果需要显示,则必须先通过RCIM的registerMessageType:注册该自定义消息类型,

并在聊天界面中通过registerClass:forCellWithReuseIdentifier:注册该自定义消息的Cell,否则将此回调将不会被调用。

- (RCMessageBaseCell *)rcConversationCollectionView:(UICollectionView *)collectionView

cellForItemAtIndexPath:(NSIndexPath *)indexPath;

自定义消息Cell显示的回调

@param collectionView          当前CollectionView

@param collectionViewLayout    当前CollectionView Layout

@param indexPath              该Cell对应的消息Cell数据模型在数据源中的索引值

@return                        自定义消息Cell需要显示的高度

@discussion 自定义消息如果需要显示,则必须先通过RCIM的registerMessageType:注册该自定义消息类型,

并在聊天界面中通过registerClass:forCellWithReuseIdentifier:注册该自定义消息的Cell,否则将此回调将不会被调用。

- (CGSize)rcConversationCollectionView:(UICollectionView *)collectionView

layout:(UICollectionViewLayout *)collectionViewLayout

sizeForItemAtIndexPath:(NSIndexPath *)indexPath;

4:总结

第三方接入,本身的难度有限,但是为了满足产品的逻辑去修改第三方的本身逻辑是最蛋疼的事情。解决问题的关键是:看文档,看官方demo,多尝试。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,980评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,422评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,130评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,553评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,408评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,326评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,720评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,373评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,678评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,722评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,486评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,335评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,738评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,283评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,692评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,893评论 2 335

推荐阅读更多精彩内容