Skip to content
This repository has been archived by the owner on Jul 2, 2019. It is now read-only.

不同的设备登陆LCCKConversationListViewController 获取不到其他设备的会话列表. #94

Closed
jidanyu opened this issue Sep 20, 2016 · 33 comments

Comments

@jidanyu
Copy link

jidanyu commented Sep 20, 2016

如题.

@ChenYilong
Copy link
Contributor

Ref: #48

@ChenYilong ChenYilong added the Q-A label Sep 20, 2016
@jidanyu
Copy link
Author

jidanyu commented Sep 22, 2016

看过#48的解决方式.我的需求是拉取所有跟自己有关的会话.看到leancloud实时消息的SDK里可以直接查询跟自己(clientId)有关的会话列表.这样不就可以不用往自己服务器传conversationId了吗?
image.

@ChenYilong
Copy link
Contributor

这是一种实现思路,不过从本地数据库读取,也有自己的好处。这两种实现暂时没想到好的方式可以进行自定义切换。

@jidanyu
Copy link
Author

jidanyu commented Nov 4, 2016

使用了#48的方案,成功在获取了conversation对象.但是数据不完全.lcck_lastMessage为空.时间也没有.

img_1748

@ChenYilong
Copy link
Contributor

.lcck_lastMessage为空.时间也没有

这个是因为他们的数据来源是本地数据库,本地数据库没有存消息,我是从数据库中的消息记录的最新一条消息来赋值的。

这个的确是个问题。

最近会添加一项新功能,将conversation对象添加一个lastMessage对象,这个对象可以作为展示消息的依据。不过这个功能发布可能需要两周时间。

@jidanyu
Copy link
Author

jidanyu commented Nov 4, 2016

了解了.

@jidanyu
Copy link
Author

jidanyu commented Nov 4, 2016

另外,就在当前的条件下.如果这个最近消息里有系统消息.通过#48的方式,然后在消息列表点击系统消息,会崩溃,原因好像是因为其中一些属性为空,比如members.这个属性现在是在本地ChatKit给它赋值,进而将系统消息伪装成群聊类型的.这个地方希望在更新功能的时候,关注一下.

@ChenYilong
Copy link
Contributor

具体crash在什么地方,我做下容错。

你先看下这个 issue #54

@jidanyu
Copy link
Author

jidanyu commented Nov 7, 2016

我确认好了,上面提到的崩溃问题是我这边可以处理的.不是ChatKit的问题.

@ChenYilong
Copy link
Contributor

ok

@jidanyu
Copy link
Author

jidanyu commented Nov 17, 2016

请问,将conversation对象添加一个lastMessage对象,最近会更新吗?

@ChenYilong
Copy link
Contributor

在做最近对话列表同步的时候,比如想达到如下效果,系统对话要做特殊处理:

在获取会话列表的基础上同时返回系统对话

具体做法参考:https://github.com/leancloud/objc-sdk/pull/120/files

@ChenYilong
Copy link
Contributor

下个版本v0.8.11会添加上自动同步最近对话记录的逻辑,思路与我上述的一致。

@ChenYilong
Copy link
Contributor

就lastMessage这个特性的回复:会在AVOSCloud的新版SDK中发布。ChatKit的v0.8.11也会根据新版SDK的实现,更新下ChatKit的内部实现逻辑。

@ChenYilong
Copy link
Contributor

目前的版本v0.8.10,最近对话列表完全依赖于本地数据库,所以目前的实现逻辑是,如果clientId第一次登陆本机是不会有最近对话列表的。但是如果该用户登出后,切换用户,再次重新登录,最近对话列表还是会有的。

v0.8.11的会作出如下更新,如果是clientId第一次登录本机,会自动同步参与的对话。之后就会完全依赖于本地数据库。
@kooyear

@kooyear
Copy link

kooyear commented Jan 6, 2017

@ChenYilong
现在的业务场景是,
用户A 登录 后,进去conversation list view,进行聊天,最近联系人出现,若直接关闭app,再次打开,conversaiton list view 被重新构造后,可以看到最近联系人。
若用户A 登录 后,进去conversation list view,进行聊天,最近联系人出现,A 执行 退出登录 的操作, B用户登入,此时 conversation list view 已经 构建,我的做法是在B登录后,在conversation list view 内执行 refresh()操作,我不知道这样的用法对不对,这个时候 A 的最近联系人被清空,B进行聊天,会出现B的最近联系人。
若此时再把B退出,A登录,此时conversation list view 已经 构建,再次执行refresh,此时看不到A的最近联系人,若关闭App,打开后,让 conversation list view在A登录后构建,是能够看到A的最近联系人,我不确定应该是用哪个方法进行用户的切换后,最近联系人列表的切换,应该如何实现?

@ChenYilong
Copy link
Contributor

实现原理上来说:openClient会根据clientId设置不同的路径来保存最近对话列表的数据库,close后并不会删除数据库,所以只要openClient之后,再refresh就会展示已有的数据库。

数据库的删除操作会在下面的情况下发生:

  • 切换了APPID
  • 手动调用接口-[LCCKConversationListService removeAllCachedRecentConversations]

如果真如你描述的最后一次登录A不显示最近对话记录,这个应该是不符合预期的。应该是会展示历史记录的。

@kooyear
Copy link

kooyear commented Jan 6, 2017

@ChenYilong

   class func invokeThisMethodBeforeLogoutSuccess(clientId:String,success:LCCKVoidBlock,failed:LCCKErrorBlock){
       
       
//        LCChatKit.sharedInstance().removeAllCachedProfiles()
       LCChatKit.sharedInstance().closeWithCallback { (succeeded, error) in
           if succeeded {
               success()
           }else{
               failed(error)
           }
       }
   }

退出时我执行了以上代码
重新登录后,
我执行了demo中的
lcck_setFetchProfiles 和

   class func invokeThisMethodAfterLoginSuccessWithClientId(clientId:String,success:LCCKVoidBlock,failed:LCCKErrorBlock){
       
       LCChatKit.sharedInstance().openWithClientId(clientId) { (succeeded, error) in
           
           if succeeded {
               
               
               
               success()
           }else{
               failed(error)
           }
           
       }
       
       
       
   }

成功后在 coversation list view 里 执行了

 func finishSignIn(){
       
       
       refresh()
       LCChatKit.sharedInstance().didSelectConversationsListCellBlock = {
           (indexPath,conversation,controller) in
           
           
           let c = controller.tableView.cellForRowAtIndexPath(indexPath) as! LCCKConversationListCell
           
           
           
           let vc = LCCKConversationViewController(conversationId: conversation.conversationId)
           
           
           vc.disableTitleAutoConfig = true
           vc.viewDidLoadBlock = {
               
               (v) in
               v.navigationItem.title = c.nameLabel.text
               
           }
           
           ViewControllerUtility.baseNavController.navigationController?.pushViewController(vc, animated: true)
           
       }
       
       
   }

refesh 后,该页面出现的最近联系人就空了,但是,此时,直接关闭app,再打开进入,conversation list view ,最近联系人又会出现,我以上的流程存在问题吗?

@ChenYilong
Copy link
Contributor

finishSignIn里要执行 invokeThisMethodAfterLoginSuccessWithClientId

@ChenYilong
Copy link
Contributor

invokeThisMethodAfterLoginSuccessWithClientId需要在每次finishSignIn执行后执行。

@ChenYilong
Copy link
Contributor

refresh方法是不需要你自己去调用的,invokeThisMethodAfterLoginSuccessWithClientId执行后会自动调用。你为什么要手动调用?可能是你方法调用顺序的问题。/

@kooyear
Copy link

kooyear commented Jan 6, 2017

@ChenYilong
finishSignIn 里的内容我的确是在 invokeThisMethodAfterLoginSuccessWithClientId 后去执行的,,及时我不调用 refresh,去掉之后,在那个页面下拉刷新,所有的联系人会被清空。

@ChenYilong
Copy link
Contributor

切换用户需要重新实例化一个新的conversationViewController对象,因为dataSource都是在viewDidLoad方法里做的。

@ChenYilong
Copy link
Contributor

我把关键的实现原理给你介绍下,你排查下是哪里出了问题:

##1. openClient会根据clientId设置不同的路径来保存最近对话列表的数据库,close后并不会删除数据库,所以只要openClient之后,再refresh就会展示已有的数据库。

具体代码见: -[LCCKConversationService setupDatabaseWithUserId:];

##2. 重新openClient后,会从数据库中,根据当前ClientId找到SQL路径,获取所有的对话记录。具体的查询方法见下:

- (NSMutableDictionary *)conversationDictionary{

/**
*  在内存中缓存对话,避免反复查询数据库,与数据库保持一致,只对数据库只做增、删、改操作。
*/
- (NSMutableDictionary *)conversationDictionary {
   if (!_conversationDictionary) {
       _conversationDictionary = [[NSMutableDictionary alloc] init];
       [self.databaseQueue inDatabase:^(FMDatabase *db) {
           FMResultSet  *resultSet = [db executeQuery:LCCKConversationTableSelectSQL withArgumentsInArray:@[]];
           while ([resultSet next]) {
               AVIMConversation *conversation = [self createConversationFromResultSet:resultSet];
               BOOL isAvailable = conversation.createAt;
               if (isAvailable) {
                   [_conversationDictionary setObject:conversation forKey:conversation.conversationId];
               }
           }
           [resultSet close];
       }];
   }
   return _conversationDictionary;
}

因为closeClient后会销毁对应的ConversationListService对象,所以重新openClient后会触发懒加载。

相关销毁过程见:

你可以打断点看下中间哪个步骤出了问题,如果懒加载时获取的数据为nil,你再去沙盒里看下数据库数据是否真的为空。

@kooyear
Copy link

kooyear commented Jan 6, 2017

@ChenYilong
如果如您所说的每次切换用户都需要实例化新的conversationViewController,问题应该出在这里,因为我每次切换完用户,还是使用的之前的那个viewController,因为我的viewController是tabbar view 的一个子tab,不清楚如果再次初始化一个。有办法还使用之前那个viewcontroller吗?

@kooyear
Copy link

kooyear commented Jan 6, 2017

@ChenYilong 发现问题似乎出现在log out 上,如果app在已经log in 的状态直接关闭程序,再次打开,即时不执行invokeThisMethodAfterLoginSuccessWithClientId ,依然可以看到聊天历史记录。若做过一次log out,或者进入程序的时候状态并不是log in ,那么即使Conversation view 没有打开过,进行log in 操作后 打开,依然看不到最近联系人。但是,若此时以一个login 的状态,直接退出程序,再次打开,直接进入Conversation view,又能看到了最近联系人,请问问题可能出现在哪?

@ChenYilong
Copy link
Contributor

听你的描述,只有

若做过一次log out,或者进入程序的时候状态并不是log in ,那么即使Conversation view 没有打开过,进行log in 操作后 打开,依然看不到最近联系人

这个操作是不符合预期的

@ChenYilong
Copy link
Contributor

其中

进行log in 操作后 打开

这个我不确定log in操作做了什么操作。如果log in 后执行了invokeThisMethodAfterLoginSuccessWithClientId 也就是进行了openClient操作,因为数据全部来自SQL,所以如果在本机上产生过历史记录,是应该能看到聊天记录的。

@kooyear
Copy link

kooyear commented Jan 16, 2017

@ChenYilong
Log in 后 就做了 lcck_setFetchProfiles操作 和 LCChatKitExample.invokeThisMethodAfterLoginSuccessWithClientId 操作, 然后在进去Conversation 界面,就看不到任何东西。如果直接关闭app,再次开启后,直接执行lcck_setFetchProfiles和invokeThisMethodAfterLoginSuccessWithClientId后就能看见,是不是有什么东西在启动的时候被执行了,要求是在登录的状态

@ChenYilong
Copy link
Contributor

ChenYilong commented Feb 8, 2017

然后在进去Conversation 界面,就看不到任何东西。

指的是最近对话列表?

@kooyear
Copy link

kooyear commented Feb 9, 2017

@ChenYilong 对的没错,是指最近联系人列表,我现在不知道该如何debug,理论上下拉刷新不是应该加载最近联系人记录吗?如果数据存在数据库的话,应该会被加载出来,但是并没了,若直接退出了再进入app再进入这个最近联系人列表,是可以看到最近联系人的,是不是说明其实数据还是在数据库里,只是因为某种原因之前的方式没有取出来。这个问题困扰我们很久了,我们是Leancloud的付费用户,不知道有没有更直接的技术指导方式

@ChenYilong
Copy link
Contributor

ChenYilong commented Feb 10, 2017

Debug的方法的话,首先可以尝试在ChatKit原生Demo的基础上能否复现该问题,如果能复现说明是ChatKit的问题,如果不是很可能是用法问题,如果这样需要你提供一个Demo,或者更多代码示例。邮箱:luohanchenyilong@163.com

@dabasir
Copy link

dabasir commented Jan 18, 2019

@ChenYilong 发现问题似乎出现在log out 上,如果app在已经log in 的状态直接关闭程序,再次打开,即时不执行invokeThisMethodAfterLoginSuccessWithClientId ,依然可以看到聊天历史记录。若做过一次log out,或者进入程序的时候状态并不是log in ,那么即使Conversation view 没有打开过,进行log in 操作后 打开,依然看不到最近联系人。但是,若此时以一个login 的状态,直接退出程序,再次打开,直接进入Conversation view,又能看到了最近联系人,请问问题可能出现在哪?

跟退出登录的机制有关,是个bug,原因是退出登录后LCCKConversationService里的conversationDictionary不是nil,再次登录成功后,不会从本地缓存中读会话列表。在invokeThisMethodAfterLoginSuccessWithClientId的一开始加上下面代码可以解决这个问题:
// 销毁这个单例,防止退出登录后再次登录,不显示会话列表
[LCCKConversationService destroyInstance];

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

4 participants