我有一个从Realm填充的UICollectionView。有些用户似乎随机获得一个NSInternalInconsistencyException,声明类似
无效更新:第0部分中的项目数无效 更新后的现有部分中包含的项目(73)必须是 等于该部分之前包含的项目数 更新(73),加上或减去插入或删除的项目数 从该部分(插入1,删除0)和加号或减号 物品移入或移出该部分(0移入,0移出)。
我的代码基于Realm的集合示例。它选择并过滤一些记录:
self.assets = realm.objects(Asset.self).filter("is_deleted = false")
然后它订阅并处理通知:
self.assetsNotificationToken = self.assets!.addNotificationBlock(){ [weak self] (changes: RealmCollectionChange) in
guard let collectionView = self!.collectionView else { return }
guard let strongSelf = self else { return }
switch changes {
case .Initial:
collectionView.reloadData()
case .Update(let _, let deletions, let insertions, let modifications):
strongSelf.collectionView?.performBatchUpdates({
collectionView.insertItemsAtIndexPaths(insertions.map { NSIndexPath(forRow: $0, inSection: 0) })
collectionView.reloadItemsAtIndexPaths(modifications.map { NSIndexPath(forRow: $0, inSection: 0) })
collectionView.deleteItemsAtIndexPaths(deletions.map { NSIndexPath(forRow: $0, inSection: 0) })
}, completion: nil)
case .Error(let error):
log.error(error.localizedDescription)
break
}
}
计数来自:
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
guard assets != nil else {
return 0;
}
return assets!.count
}
我后来切换到RealmGridController
无法找到崩溃的来源,我切换到RealmGridController。它是由Realm核心贡献者编写的软件包,它封装了使用realm + CollectionViews所需的所有标准功能。
它似乎工作,然后我开始看到完全相同的崩溃。
致命异常:NSInternalInconsistencyException无效更新: 第0节中的项目数无效。包含的项目数 更新后的现有部分(78)必须等于数字 更新前该部分中包含的项目(78),加或 减去从该部分插入或删除的项目数量(2 插入,0删除)并加上或减去移入的项目数 或超出该部分(0移入,0移出)。
Fatal Exception: NSInternalInconsistencyException
0 CoreFoundation 0x1839dadb0 __exceptionPreprocess
1 libobjc.A.dylib 0x18303ff80 objc_exception_throw
2 CoreFoundation 0x1839dac80 +[NSException raise:format:]
3 Foundation 0x184360154 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:]
4 UIKit 0x18938b00c -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:]
5 UIKit 0x18938e464 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:]
6 UIKit 0x18938e2e0 -[UICollectionView _performBatchUpdates:completion:invalidationContext:]
7 UIKit 0x188d2c2a4 -[UICollectionView performBatchUpdates:completion:]
8 RealmGridController 0x1014a8340 specialized RealmGridController.controllerDidChangeContent(RBQFetchedResultsController) -> () (RealmGridController.swift:316)
9 RealmGridController 0x1014a687c @objc RealmGridController.controllerDidChangeContent(RBQFetchedResultsController) -> () (RealmGridController.swift)
10 RBQFetchedResultsController 0x100ff8edc __112-[RBQFetchedResultsController calculateChangesWithAddedSafeObjects:deletedSafeObjects:changedSafeObjects:realm:]_block_invoke.433 (RBQFetchedResultsController.m:842)
11 libdispatch.dylib 0x1834254bc _dispatch_call_block_and_release
答案 0 :(得分:2)
RealmGridController
是在Realm支持细粒度通知之前编写的库,因此它实现了许多自定义逻辑以获得相同的结果。我强烈建议你恢复原来的逻辑,因为那个逻辑已深深融入Realm本身。
要记住的一件重要事情是Realm查询结果是活动对象;它们会在每次运行循环迭代时自动更新,以包含发生在其中的任何更改。因此,self.assets
的内容应始终与您的集合视图显示的内容直接一对一关联。细粒度通知通知仅用作更新任何过时UI元素的机制,并且在调用时,self.assets
已经处于最新状态。
您可能需要提供有关应用在运行时修改self.assets
内容的更多信息。如何添加和删除元素?您的应用程序中是否发生了并发?
您需要非常小心,不要进行任何手动UI更新,因为任何意外的偏离集合视图的先前状态以及Realm假设需要更新的内容都会产生这些不一致的异常。
答案 1 :(得分:1)
在我的情况下,我有一个刷新和无限加载的拉力。
当我想刷新时,我正在删除所有对象,以便在Web服务调用之前获取新的新数据。
try! Realm().write {
let demands = Realm().objects(Demand.self)
for demand in demands {
Realm().delete(demand)
}
}
哪个触发了更改通知,但在有时间为删除操作动画之前,我收到了一个新项目的Web服务响应,创建了NSInternalInconsistencyException
所以我试过了:
try! Realm().write {
let demands = Realm().objects(Demand.self)
for demand in demands {
Realm().delete(demand)
}
}
collectionView?.reloadData()
它没有用。然后我最终做了:
try! Realm().write {
let demands = Realm().objects(Demand.self)
for demand in demands {
Realm().delete(demand)
collectionView?.reloadData()
}
}
它有效!想法是在调用通知之前重新加载CollectionView。 希望它可以帮到某人。
注意:我在模拟器上没有任何问题,仅在真正的iPhone 6设备iOS 10上。