美文网首页对于iOS集成SDK方面的文章融云IM
iOS融云聊天实现出现的问题以及实现半屏聊天记录(补充解决同安卓

iOS融云聊天实现出现的问题以及实现半屏聊天记录(补充解决同安卓

作者: 丶烟树 | 来源:发表于2016-12-31 17:40 被阅读1347次

近期项目中要接入聊天,相对于直播来说这只是一个小需求,但是中间也有一些坑以及挣扎了好久的半屏聊天的实现。
1.首先先说下实现正常的聊天,讲真,融云的文档写的是真不怎么样,模棱两可,首先看下他的

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

方法,按照文档上写的是两个用户,但是写法是一样的,给人一种错觉就是if else 里面只要写一样的就行了,我在后面的操作中也把自己的以及我要聊天的人的信息上传上去了,但是经实践是不对的,而且这个方法是只用实现一次的,也就是在appdelegate里面登录成功后实现一次这个方法就行了,不用每次给谁聊天都掉一下这个方法,正确的写法是if里面给融云上传自己的信息,在else里面请求一下自己服务器userid的数据,这个userid就是你要聊天对象的id再把请求的头像、昵称赋值给

   RCUserInfo *user = [[RCUserInfo alloc]init];
    user.userId = userInfo.member_id;
    user.name = userInfo.basic_info.nickname;
    user.portraitUri = imageUrl;

针对这一块我是写了一个单例,RongYunUserInfo,因为融云的token是有期限的,所以在登录成功之后需要校验rongyun_token是否为空,如果为空,再去服务器请求一下token
2.搞定了头像昵称的显示,列表显示正常了,但是从会话列表跳转到聊天列表,聊天记录不显示了,必须手动刷一次才能正常显示,各种检查代码,都是没问题的,最后没招,只能提工单了,结果答案是在设置所有RCConversationListViewController属性之前必须先设置

chatRoomScene.targetId = model.targetId;
chatRoomScene.conversationType = model.conversationType;

真蛋疼。设置完成之后,好了,聊天的正常事项我们都完成了,下面就是半屏聊天了。
3.实现半屏可能这个方法不是最好的,有更好的方法请告知,先说下我最初的实现方法,也给大家规避一些不好的实现方法,因为,我们是有两个聊天
,外面的完成界面的聊天,里面要实现一个高度只有290的mini聊天界面,但是界面是一样的,


屏幕快照 2016-12-31 下午4.07.48.png

(1)因为最初的聊天、消息是在导航栏上面设置的,正常的VC是不能设置坐标的,后来想到了用特殊的转场动画来实现,因为转场动画是可以设置toVC.view = 290的坐标实现一个mini的VC,这样既保留了导航栏的会话列表还能push到聊天界面,想想都很美好,说干就干了,找了一个简书上一个大神写的VC转场动画,基本都实现了,很开心,但是马丹,我从聊天界面跳转回会话列表的时候,会话列表又变成全屏的了,无论怎么去设置从转场进来的containView的坐标都不行,甚至用了最low的方法,从新拿到做转场动画的主VC的superView来设置也不行,至此,这个方法宣布GG,而且这个方法还有一个致命的问题,当然这个问题不是我们的原因,是融云不支持我们去修改工具栏RCChatSessionInputBarControl的坐标,用转场动画toVC是正常的,从toVC push的聊天界面的样式也是符合要求的minivC,但是他的坐标是按照全屏显示的,虽然导航栏显示的是push过来的,但是RCChatSessionInputBarControl还是在从导航栏开始为起始点屏幕的高度为终止点的位置,聊天的collectionView坐标是可以修改的,但是RCChatSessionInputBarControl不能修改,修改了虽然可以看到,但是不响应点击事件。这样就不能这样做了。
(2)既然要保证RCChatSessionInputBarControl在最下方不能修改,后来想到了用presentViewController来实现,分别present一个回话列表和一个聊天界面,现在有一个问题就是我们需要去更改present出来的VC的透明度,因为present出来vc是吧下面遮盖的,就在网上找到了下设置你要present VC的这三个属性就可以了

 chatRoomScene.definesPresentationContext = YES;
   chatRoomScene.modalPresentationStyle = UIModalPresentationOverCurrentContext;
   chatRoomScene.view.backgroundColor = [UIColor clearColor];

这个地方以及下面的设置都是基于判断是present的是miniVC才这样设置,正常的聊天我们还是按照融云的正常聊天就行了


35CAEE2A-0F8A-446B-8D26-B1C219711B88.png

还是按照上面的方法跳转到聊天界面,因为他是全屏VC我们是可以去修改他的conversationMessageCollectionView的坐标,这样保证了不用修改工具栏的坐标,再自定义一个导航栏就可以了


460544A0-25EF-40BC-B6A2-4A8D3C45313B.png
中间需要去做的就是去监听键盘的弹出以及表情View弹出我们去修改试图的坐标以及自己造的导航栏的坐标动态修改一下试图的坐标就可以了
DFE4BCC8-CA0B-422C-A12D-84639389CE8F.png 1933CB43-A025-453E-B25C-1FC009AB974B.png

因为他的列表还是按照全屏显示的,我们再让列表自动滚动到最下方

 //滚动到最下面
        NSUInteger finalRow = MAX(0, [self.conversationMessageCollectionView numberOfItemsInSection:0] - 1);
        if (0 == finalRow) {
            return;
        }
        NSIndexPath *finalIndexPath = [NSIndexPath indexPathForItem:finalRow inSection:0];
        [self.conversationMessageCollectionView
         scrollToItemAtIndexPath:finalIndexPath
         atScrollPosition:UICollectionViewScrollPositionBottom
         animated:NO];

其中有一个问题就是返回上一级会话列表的时候数据不会和正常的聊天一样进行数据刷新,这也是唯一的不足,我的做法是在聊天界面disappear的时候发一个通知让会话列表去刷新

   [[[[NSNotificationCenter defaultCenter]
      rac_addObserverForName:@"RefreshMessageScene" object:nil]
     takeUntil:[self rac_willDeallocSignal]]
    subscribeNext:^(NSNotification *notification) {
        @strongify(self);
   /*!
      从数据库中重新读取会话列表数据,并刷新会话列表

      @warning 从数据库中重新读取并刷新,会比较耗时,请谨慎使用。
  */
        [self refreshConversationTableViewIfNeeded];
    }];

这个融云官方是不提倡的,但是没别的办法,还望谁看到了有更好办法的给我说一下。
总结,啰里啰嗦说这么多,是希望把自己走的弯路也贴出来给大家一个参考。
更新: 解决同安卓聊天无法正常显示头像昵称的问题
聊天都解决了,但是安卓大兄弟过来说咱们两端聊天的时候,我给你发消息的时候在iOS是正常的,但是你给我发消息的时候在安卓端显示不到你的头像和昵称,其实这个问题很好解决,就是上面提到的我们没法显示头像昵称的问题,因为安卓大兄弟也实现了

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

这个方法,但是呢,他里面就是我们之前说的问题请求被聊天人信息时没有实现一次网络请求,所以拿不到我的信息,当时我一直问安卓大兄弟你这个地方请求网络了吗,大兄弟很肯定的告诉我,请求了。直觉告诉我就是这个地方出问题了,我问他呢你是怎么实现的,他说是用携带消息体的方式,安卓大兄弟说他如果用代理自己这边会出问题,那就只好iOS这边改了,这里补充下,融云的消息传递是有两种方式的,一种是实现代理进行网络请求,另一种是携带消息体的方式,就是把用户消息直接包含在消息里面,实现方式,两种方式携带消息体的优先级高,会优先读取消息体,这就是咱们说为啥安卓无法显示iOS信息,因为我用的代理,而安卓用的是携带消息体,我没有携带消息体,他也没有进行网络请求,所以显示就不正常了,携带消息体的写法

    [RCIM sharedRCIM].currentUserInfo.userId = @"使用者ID";
    [RCIM sharedRCIM].currentUserInfo.name = @"名字";
    [RCIM sharedRCIM].currentUserInfo.portraitUri =@"图像";
    //设置发送的消息是否携带用户信息
    [RCIM sharedRCIM].enableMessageAttachUserInfo = YES;

这里面有个坑,因为两种实现方式,我以为实现这种方式之后就不需要再去实现代理了,问工单客服,客服也说不用再实现代理


CA6FF960-27EB-4DD1-A398-ABE3B1DF8D16.png

然后我按照他说的做了,结果就会出现这个叼样子,只会显示User<>

1948835b826b6b7affe0eee50a4fc50e.png

后来再想了下,所有的操作我都没有对用户信息进行保存,这肯定不是正确做法,
然后我又在原来的实现代理的基础上,在前面加上了携带消息体,至此,所有完结,两端显示正常,那么这就有问题了,就按照我之前说的,是两种实现方式,两者都存在很明显是不合理的,然后就又去和安卓大兄弟讨论一番,把我的想法和处理逻辑给他说了下,发现他那边在实现的代理的时候是进行网络请求,但是没有将用户信息请求下来之后再去返回给融云,所以导致了他说的他那边自己显示会有异常,然后改了下就完美解决了,咱的代码再撤销回去。。。。

2018.6.15更新
近期发现,一个用户在没有登录的情况下,收到不同的人给发的聊天消息,或者自己同时给几个人发聊天消息,这时候登录回到聊天界面,会出现几个人使用一个人的聊天头像和昵称,根据数据显示聊天列表的数据源是对的,但是在getuserinfo的代理方法中会出现给的userid和列表数据不一致的情况(比如列表中有9条数据,但是代理方法中只会给6条左右的数据,导致无法比对数据重复的原因,是新包,无缓存情况下)给融云扯皮了两天,最后一点点排查,找到原因是在- (void)getUserInfoWithUserId:(NSString )userId completion:(void(^)(RCUserInfo userInfo))completion中调取自己服务器的userInfo后,在返回completion(userInfo)返回的时候,同时要调用 [[RCIM sharedRCIM] refreshUserInfoCache:user withUserId:x.member_id];刷新缓存的userInfo。。。

相关文章

网友评论

  • 你是我此世不渝的执着:你好 聊天详情页 滑动非常卡 因为每次都去请求接口获取头像 有什么好办法吗
  • 87e912b47ff4:请问在聊天页面的时候(继承自RCConversationViewController),收到别人发送的信息之后怎么刷新? 我现在收到别人的消息,还需要收到上拉一下才能刷新出最新的消息,请问楼主遇到过吗
    丶烟树:发送方调用[[RCIM sharedRCIM] sendMessage: 不要使用RCIMClient的sendMessage接口
    丶烟树:imlib接口是不会立即刷新的,kit接口是立马会刷新界面的,楼上说的很对,你排查下是不是调用的是lib接口发送的消息
    39bd1c661a20:你一定是设置了 IMLib接口的参数。如果用IMKit就不要用IMLib。排除下看哪里设置错了
  • 这个timo不太冷:自己的portraitUri的URL正确,但是还是显示默认头像
    丶烟树:你需要刷新下融云的缓存,调用下他的imkit的refreshuserinfo接口,
    // 刷新融云中缓存的信息
    RCUserInfo *info = [RCUserInfo new];
    info.userId = self.targetID;
    info.name = @"新的名字";
    info.portraitUri = @“新的头像地址”;

    [[RCIM sharedRCIM] refreshUserInfoCache:info withUserId: self.targetID];
  • Bales_chu:- (void)getUserInfoWithUserId:(NSString *)userId
    completion:(void (^)(RCUserInfo *userInfo))completion{
    NSString *uid = [TJAccountHelp sharedTJAccountHelp]._id;
    NSString *head = [TJAccountHelp sharedTJAccountHelp].head;
    if ([userId isEqualToString:uid]) {
    RCUserInfo *userInfo = [[RCUserInfo alloc]init];
    userInfo.userId = userId;
    userInfo.name = [TJAccountHelp sharedTJAccountHelp].name;
    userInfo.portraitUri = head;
    [RCIM sharedRCIM].enableMessageAttachUserInfo = YES;
    return completion(userInfo);
    }


    return completion(nil);
    }
    我在代理里边这么写了 安卓端也是发送的消息体 但是开始我没有加 [RCIM sharedRCIM].enableMessageAttachUserInfo = YES;这句的时候,安卓的头像能在我这边显示 我加了这段代码 就不显示了 怎么回事?
    Bales_chu:@丶烟树 我现在有时候会出现这个问题 有时候不会 不知道哪里出了问题
    丶烟树:@Bales_chu 不好意思 这段时间工作比较忙 好久没登简书了 不知道你的问题解决了没?

本文标题:iOS融云聊天实现出现的问题以及实现半屏聊天记录(补充解决同安卓

本文链接:https://www.haomeiwen.com/subject/lcazpttx.html