UICollectionView不会scrollToItem(at:IndexPath,at:position)

时间:2019-11-04 14:05:05

标签: ios swift uicollectionview

我正在使用此方法滚动我的收藏夹视图。

import UIKit
extension UICollectionView {
    func scrollToLast() {
        guard numberOfSections > 0 else {
            print("number of sections < 0")
            return
        }
        let lastSection = numberOfSections - 1
        guard numberOfItems(inSection: lastSection) > 0 else {
            print("number of items < 0")
            return
        }
        let lastItemIndexPath = IndexPath(item: numberOfItems(inSection: lastSection) - 1,
                                          section: lastSection)
        self.scrollToItem(at: lastItemIndexPath, at: .centeredVertically, animated: true)
        print("last Item (section, item #): \(lastItemIndexPath)")
    }
}

在加载视图并且集合视图中包含项之后,我才调用此方法。直到我在单元格原型中添加标签之前,它一直在工作,现在,尽管使用新标签看起来像该视图,但是使用此方法不会滚动任何内容。我仍然可以手动滚动视图。注意:调用该方法时,上述方法的输出正确列出了最后一个indexPath的最后一项。

控制台中出现以下警告/错误,但似乎与滚动调用时不一致,所以不确定其相关性:

  

2019-11-04 06:01:13.017384-0800 AppName [17598:4494554] [CollectionView]在prepareLayout调用正在进行中(即,可重入调用)时尝试准备布局的尝试已被忽略。请提交错误。 UICollectionView实例为(; layer =; contentOffset:{0,0}; contentSize:{0,0}; AdjustedContentInset:{0,0,0,0};布局:; dataSource:appBundle.instance

我如何称呼它为例:(这在viewDidLoad中)

DataService.instance.messageListener(roomId: room.id, { (result) in
        self.messageArr.append(result)
        self.messageArr = self.messageArr.sorted(by: { $0.date < $1.date})
        self.collection.reloadData()
        self.collection.scrollToLast()
        self.messageTextArea.text = ""
})

编辑:我已经删除了对主队列的所有调用,并且行为已更改。现在,当触发messageListener方法时,该视图将滚动到集合视图的顶部,但是在其他地方使用相同的scrollToLast()方法时,该视图将按原样滚动到最后一个项目-但只有 after < / em>将该视图手动滚动到底部。我还尝试按照下面的答案将代码移至viewDidAppear,但没有任何效果。

3 个答案:

答案 0 :(得分:1)

它与您的问题无关,但我有一些建议:
1)您无需在调用self.scrollToItem之前调用DispatchQueue.main.async,因为您已经在DataService.instance.messageListener中切换到了主线程。
2)messageArr有潜在的多线程问题,因为您是从DataService messageListenercompleteHandlers线程中编辑的(它可能在线程上)。据我了解,messageArr是您的集合视图的数据源。因此,当您滚动集合视图或重新加载它时,collectionView将从主线程访问messageArr。这将导致崩溃或不确定的行为,因为您从两个线程访问了messageArr数组而没有锁定。解决方案之一就是将整个DataService.instance.messageListener完成处理程序异步到主队列。

    DataService.instance.messageListener(roomId: room.id, { (result) in
        DispatchQueue.main.async {
            self.messageArr.append(result)
            self.messageArr = self.messageArr.sorted(by: { $0.date < $1.date })
            self.collection.reloadData()
            self.collection.scrollToLast()
            self.messageTextArea.text = ""
        }
    })

答案 1 :(得分:1)

调用viewDidLoad时,将加载所有视图,但是我发现集合视图和表视图不一定已加载所有数据。尝试改为在viewWillAppearviewDidAppear中调用滚动方法。

答案 2 :(得分:0)

我不确定为什么该方法不起作用,但是我将方法更改为滚动到内容视图的底部,而不是滚动到特定项目,这种方法可以很好地解决。这不应该是该问题的公认答案,所以我将其保留为开放状态,以防有人可以解决原始问题。

以下是解决方法:

g.E().hasLabel('history').order().by(outV().id())
{"requestId":<stuff>,"code":"UnsupportedOperationException","detailedMessage":
"com.amazon.neptune.storage.volcano.ast.CutoffNode cannot be cast to 
com.amazon.neptune.storage.volcano.ast.AbstractGroupNode"}