[英]UICollectionView Won't scrollToItem(at: IndexPath, at: position)
我正在使用這種方法來滾動我的收藏視圖。
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)")
}
}
在視圖加載並且集合視圖中有項目之前,我不會調用此方法。 它之前一直在工作,直到我將 label 添加到我的單元原型中,現在雖然視圖看起來與新的 label 一樣,但使用此方法不會滾動任何內容。 我仍然可以手動滾動視圖。 注意:上述方法的output在調用該方法時正確列出了最后一個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}; layout: ; 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()
方法時,視圖會滾動到它應該的最后一項 - 但只有在視圖手動滾動到底部。 我也嘗試根據下面的答案將代碼移動到viewDidAppear
,但沒有任何效果。
這與您的問題無關,但我有一些建議:
1)調用self.scrollToItem之前不需要調用DispatchQueue.main.async,因為在DataService.instance.messageListener中已經切換到主線程。
2) messageArr 存在潛在的多線程問題,因為您從 DataService messageListener completionHandlers 線程中編輯了它(它可能在線程上)。 據我了解 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 = ""
}
})
當調用viewDidLoad
時,所有視圖都將被加載,但我發現集合視圖和表視圖不一定已經加載了所有數據。 嘗試在viewWillAppear
或viewDidAppear
中調用您的滾動方法。
我不確定為什么此方法不起作用,但我已將方法更改為滾動到內容視圖的底部而不是滾動到特定項目,這可以作為一種解決方法。 這不應該是這個問題的公認答案,所以我會保持打開狀態,以防有人可以解決原始問題。
這是解決方法:
extension UICollectionView {
func scrollToBottomOfContent() {
let contentHeight: CGFloat = self.contentSize.height
let heightAfterInserts: CGFloat = self.frame.size.height - (self.contentInset.top + self.contentInset.bottom)
if contentHeight > heightAfterInserts {
self.setContentOffset(CGPoint(x: 0, y: self.contentSize.height - self.frame.size.height), animated: true)
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.