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内容