我正在将当前的UITableview更新为iOS 13 UITableViewDiffableDataSource
提供的可扩散数据源。
我有一个带有自定义对象的数组(实现isEqual:方法)。在viewWillAppear上,我从磁盘加载数据并致电申请快照。
-(void)updateTableViewAnimated:(BOOL)animated API_AVAILABLE(ios(13.0)){
NSDiffableDataSourceSnapshot *snapshot = [[NSDiffableDataSourceSnapshot alloc]init];
[snapshot appendSectionsWithIdentifiers:@[@"sectionTitle"]];
[snapshot appendItemsWithIdentifiers:self.playlists];
[self.diffDataSource applySnapshot:snapshot animatingDifferences:animated];
}
一切都加载了。但是,当尝试从数组中删除一项并再次调用updateTableViewAnimated:
时,我得到了一个例外。
***由于未捕获的异常“ NSInvalidArgumentException”而终止应用程序,原因:“移动关联不一致”
是什么意思? 我该怎么解决?
答案 0 :(得分:7)
在Jasarien信息丰富的答案中,
您需要记住,UICollectionViewDiffableDataSource
使用hashable来区分数据源中的项目
如果您的模型是结构,并且数据源模型中有两个项目恰好具有完全相同的值,则Hashable
协议会为它们生成相同的hashValue。
Equatable
协议也将返回true! ,这会造成混乱
UICollectionViewDiffableDataSource
解决方案
Equatable
,则可能想在数据源中添加随机值,但是不建议这样做,因为生成的值在任何巧合上都可能相等,如文献所述
*可能性低,但可能会发生* 根据范围的大小和范围,某些具体值可能比其他具体值更频繁地表示。
答案 1 :(得分:4)
我很幸运能够得到我对此提出的错误的答复。事实证明,我的模型对象的哈希和相等检查不正确。
我的快捷结构符合Hashable,但提供了Equatable的自定义实现,因此我仅比较ID属性来确定相等性。这意味着有可能将两个对象视为相等,但具有不同的哈希值,这会混淆区分算法。
要解决此问题,我只是删除了自定义的Equatable实现,并使用了综合版本。
您在问题中指出,您实现了isEqual
,类似于Swift的==
的ObjC,但是您可能未提供与{{1 }}实施。
我不知道这是否与您遇到的问题相同,但就我而言,这是由从不同队列调用hash
方法引起的。
Advanced Data Sources WWDC会话提到isEqual
必须在后台队列或主队列上被独占调用,但不要同时从两者中调用。 Advanced Data Sources WWDC 2019-32:00
在我的情况下,我使用的是Combine发布者来对我的数据源上的更改做出反应,而该发布者有时会在主线程或后台线程上发送值。为了解决我的问题,我在链中添加了applySnapshot
。
在您的情况下,也许您可以使用希望其在其上运行的队列(无论是主队列还是后台队列)将可以调用applySnapshot
的任何内容包装在.receive(on: RunLoop.Main)
调用中。