我正在我的应用程序上构建一个屏幕,配置文件将显示在集合视图中。我的数据是从Firebase中检索的,这是我第一次使用Firebase DatabaseUI。
我正在构建一个查询,然后创建一个FUICollectionViewDataSource
,对我的单元格进行排队,然后将该dataSource插入collectionView。
只要我在在线和离线用户之间切换(这会检查查询上子键的值),dataSource的功能就可以正常工作,但当我将查询从男性更改为女性,或从女性更改为男性时(这本身就是一个新的查询),我会遇到NSInternalInconsistenencyException
。
***由于未捕获的异常"NSInternalConferenceException"而终止应用程序,原因:"无效更新:节0中的项目数无效。"。更新后现有节中包含的项目数(1)必须等于更新前该节中包含项目的数量(1),加上或减去从该节中插入或删除的项目数量(插入1个,删除0个),再加上或减上移入或移出该节的项目数量(移入0个,移出0个)。">
***首次抛出调用堆栈:(0x18672d1b8 0x18516455c 0x18672d08c 0x1871e502c 0x18cedc14c 0x18c7b1d4c 0x10020f594 0x1002102c8 0x1001eb3e0 0x101609258 0x101609218 0x10160e280 0x1866da810 0x1866d83fc 0x1866062b8 0x1880ba198 0x18c64d7fc 0x18c648534 0x1000c4200 0x1855e95b8)libc++abi.dylib:以NSException 类型的未捕获异常终止
当我构建集合视图时,我习惯于只运行这样的命令:
collectionView.dataSource = collectionViewDataSource
self.collectionView.reloadData()
但现在,像上面这样的调用不起作用,而且我没有使用UICollectionViewDataSource
协议函数,我不确定如何创建、运行和显示新的查询,因为每个部分的项目数总是不同的。
在处理新查询之前,我必须运行哪些函数才能避免此类崩溃?
我已经尝试从collectionView的indexPathsForVisibleItems
中删除所有单元格,然后重新加载数据。。。我把collectionView.reloadData()
扔得到处都是,但还是崩溃了。不是所有的时间,但应用程序迟早会崩溃。
如何在collectionView上启动全新的查询,而不必处理NSInternalInconsistencyExceptions
?
谢谢大家。我喜欢Firebase,很想弄清楚这一点!
-Reezy
VC加载时,会调用getUserData()
函数。当查询发生更改时,resetQuery()
函数将从发布的通知中运行。
extension BrowseVC {
func getUserData() {
let isOnline = (segmentedControl.selectedSegmentIndex == 0) ? true : false
generateQuery(isOnline: isOnline)
populateDataSource()
}
func resetQuery() {
removeOldData()
getUserData()
}
func removeOldData() {
let indexPaths = collectionView.indexPathsForVisibleItems
collectionView.deleteItems(at: indexPaths)
// collectionView.reloadData()
}
func generateQuery(isOnline: Bool) {
if let selectedShowMe = UserDefaults.sharedInstance.string(forKey: Constants.ProfileKeys.ShowMe) {
let forMen = (selectedShowMe == Constants.ProfileValues.Men) ? true : false
query = FirebaseDB.sharedInstance.buildQuery(forMen: forMen, isOnline: isOnline)
} else {
query = FirebaseDB.sharedInstance.buildQuery(forMen: false, isOnline: isOnline)
}
}
func populateDataSource() {
if let query = query {
collectionViewDataSource = FUICollectionViewDataSource(query: query, view: collectionView, populateCell: { (view, indexPath, snapshot) -> ProfileCVCell in
if let cell = view.dequeueReusableCell(withReuseIdentifier: Constants.CollectionViewCellIdentifiers.ProfileCVCell, for: indexPath) as? ProfileCVCell {
if let userDictionary = snapshot.value as? [String: AnyObject] {
if let user = User(uid: snapshot.key, userDictionary: userDictionary) {
cell.populate(withUser: user)
}
}
return cell
}
return ProfileCVCell()
})
collectionView.dataSource = collectionViewDataSource
collectionView.reloadData()
// collectionView.performBatchUpdates({
// self.collectionView.dataSource = self.collectionViewDataSource
// }, completion: nil)
// collectionView.reloadData()
}
}
}
遇到这种情况的原因是FirebaseUI数据库数据源负责将更新推送到集合视图本身。通过这种方式,您可以免费获得动画更新,而不必调用reloadData。
将旧数据源换成新数据源时,需要将数据源的集合视图设置为nil
,以便它停止将事件推送到集合视图。