CollectionView:scrollToItem、reloadData 和调度队列

Posted

技术标签:

【中文标题】CollectionView:scrollToItem、reloadData 和调度队列【英文标题】:CollectionView: scrollToItem, reloadData, and Dispatch Queues 【发布时间】:2016-11-08 03:43:53 【问题描述】:

大家下午好,

我遇到了一个令人沮丧的错误,与我一直关注的聊天应用程序教程有关,并且想要补救(由于我已转换为 Swift 3 / Xcode8,该教程没有解决这个问题)。让我试着描述一下这个问题:

两个用户之间的聊天记录使用 Firebase 数据库来存储和检索他们之间的对话消息。我正在使用 collectionView 来显示对话。我想在聊天日志中实现一个功能,这样当用户选择要查看的对话时,它会滚动到最新/最后的“消息”,以便用户轻松地继续对话。

这里是当前聊天记录控制器的相关代码:

func observeMessages() 
    guard let uid = FIRAuth.auth()?.currentUser?.uid, let toId = user?.id else 
        return
    

    let userMessagesRef = FIRDatabase.database().reference().child("user-messages").child(uid).child(toId)
    userMessagesRef.observe(.childAdded, with:  (snapshot) in

        let messageId = snapshot.key
        let messagesRef = FIRDatabase.database().reference().child("messages").child(messageId)
        messagesRef.observeSingleEvent(of: .value, with:  (snapshot) in

            guard let dictionary = snapshot.value as? [String: AnyObject] else 
                return
            

            self.messages.append(Message(dictionary: dictionary))

            DispatchQueue.main.async(execute: 
                self.collectionView?.reloadData()

                let indexPath = IndexPath(item: self.messages.count - 1, section: 0)

                self.collectionView?.scrollToItem(at: indexPath, at: .bottom, animated: true)
            )

        , withCancel: nil)

    , withCancel: nil)

我遇到的问题是关于 collectionView 滚动到的无效 indexPath。使用打印语句,我发现 reloadData() 被调用了很多,这只是我从调试控制台的假设,即 indexPath 不能“更新”或“跟上”这些值。

我对 GCD 很陌生(我只被告知应该始终在主线程上完成 UI 的更新),并且想知道我的问题的答案是否在于设置正确的同步/异步执行,或者串行/并发队列。

Ex// 使用后台线程获取会话消息并更新 indexPath,而主线程异步地重新加载数据和 scrollsToItem。

我不确定,但如果有人能对此有所了解,或指出正确的方向,我将不胜感激。非常感谢。

【问题讨论】:

【参考方案1】:

如果你的collectionView基于

self.messages array, 

self.messages.append(Message(dictionary: dictionary)) 

也进入主线程。

所有用于主线程表(collectionView 或 tableView)的数据列表必须仅在主线程上管理。

【讨论】:

谢谢 Nikita 和 Sanju。我进行了更改,它似乎缓解了所有问题。从现在开始,我一定会在主线程上维护数据列表。

以上是关于CollectionView:scrollToItem、reloadData 和调度队列的主要内容,如果未能解决你的问题,请参考以下文章

为啥 CollectionView 单元格内部其他 collectionView 的大小错误?

CollectionView 单元格出现在 collectionView 之外。

CollectionView 里面的 CollectionView | CollectionViewCell 自动布局错误

当collectionView折叠时隐藏collectionView内容

普通 CollectionView 单元格中的动态 CollectionView 单元格

CollectionView 嵌套在 Collectionview 中