【发布时间】:2017-03-21 12:51:48
【问题描述】:
我在我的项目中使用 Realm 来编写来自 API 的实时数据并同时填充 UICollectionView。为了实现这一点,我一直在使用 Realm 的 Collection Notification (https://realm.io/docs/swift/latest/#collection-notifications) 来观察插入。我遇到的问题是,当我在集合视图中使用多个部分时,总是会出现以下错误:
由于未捕获的异常而终止应用程序 'NSInternalInconsistencyException',原因:'无效更新:无效 第 2 节中的项目数。 更新后的现有节(4)必须等于 更新前该部分中包含的项目 (3),加号或减号 从该部分插入或删除的项目数(0 插入, 0 已删除)加上或减去移入或移出的项目数 该部分(0 移入,0 移出)。'
每次从 API 收到新项目时,我需要刷新集合视图中的 3 个部分。当我有 1 个部分时它可以完美运行,但当我有 3 个部分时会导致崩溃。为此,我有一个 NotificationToken 数组,并且我观察到新的插入:
internal func observeResults(results: Results<SJResult>, section: Int) {
notificationTokens.append(results.addNotificationBlock { [weak self] (changes: RealmCollectionChange) in
switch changes {
case .initial:
collectionView.reloadData()
break
case .update(_, let deletions, let insertions, let modifications):
collectionView.performBatchUpdates({
collectionView.insertItems(at: insertions.map { IndexPath(row: $0, section: section) })
collectionView.deleteItems(at: deletions.map { IndexPath(row: $0, section: section) })
collectionView.reloadItems(at: modifications.map { IndexPath(row: $0, section: section) })
})
break
case .error(let error):
fatalError("\(error)")
break
}
})
}
我正在这样的后台队列中写入结果:
DispatchQueue.global(qos: .background).async { [weak self] in
for (index, group) in groups.enumerated() {
let result = Item(group: group)
if let realm = try? Realm() {
do {
try realm.write {
realm.add(result)
}
} catch let exception {
print("Can't write result: \(exception)")
}
}
}
}
这就是我指定每个部分中的项目数的方式:
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return results(leg: section).count // Query the table to get the results I want to display
}
似乎当集合视图在插入新元素时(在collectionView.performBatchUpdates中),有时会同时在数据库realm.add(result)上写入新项目,这导致崩溃的总数项目在更新的开始和结束之间发生了变化。我设法通过同步写入DispatchQueue.global(qos: .background).sync 来避免崩溃,这会导致一些性能问题。我真的很想异步编写任何新项目,但我不知道它为什么会崩溃。请问有谁知道发生了什么以及如何改进?
【问题讨论】:
标签: ios swift uicollectionview realm