iOS 13上TableView错误的可疑数据源:移动关联不一致

时间:2019-08-01 13:18:31

标签: objective-c uitableview ios13

我正在将当前的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”而终止应用程序,原因:“移动关联不一致”

是什么意思? 我该怎么解决?

2 个答案:

答案 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

Advanced Data Sources WWDC 2019

在我的情况下,我使用的是Combine发布者来对我的数据源上的更改做出反应,而该发布者有时会在主线程或后台线程上发送值。为了解决我的问题,我在链中添加了applySnapshot

在您的情况下,也许您可​​以使用希望其在其上运行的队列(无论是主队列还是后台队列)将可以调用applySnapshot的任何内容包装在.receive(on: RunLoop.Main)调用中。