Fab*_*oft 6 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];
}
Run Code Online (Sandbox Code Playgroud)
一切都加载了。但是,当尝试从数组中删除项目并再次调用时updateTableViewAnimated:,出现异常。
***由于未捕获的异常“ NSInvalidArgumentException”而终止应用程序,原因:“移动关联不一致”
这是什么意思?我该如何解决?
Jas*_*ien 37
我很幸运地得到了对我就此提出的错误的回应。事实证明,我的模型对象进行了不正确的哈希和相等检查。
我的 swift 结构符合 Hashable,但提供了 Equatable 的自定义实现,因此我只比较 ID 属性来确定相等性。这意味着两个对象可能被认为是相等的,但具有不同的哈希值,这会混淆差异算法。
为了解决这个问题,我简单地删除了 Equatable 的自定义实现,并使用了合成版本。
您在问题中声明您实现isEqual了 ObjC,类似于 Swift 的==,但是您可能没有提供在所有情况下hash都与您的isEqual实现一致的实现。
我不知道这是否与您遇到的问题相同,但在我的情况下,它是由applySnapshot从不同队列调用的方法引起的。
高级数据源 WWDC 会话提到applySnapshot必须在后台队列或主队列上独占调用,但不要从两者调用。高级数据源 WWDC 2019 - 32:00
在我的例子中,我使用一个 Combine 发布者来对我的数据源上的变化做出反应,并且该发布者有时会在主线程或后台线程上发送值。为了解决我的问题,我添加.receive(on: RunLoop.Main)到链中。
在您的情况下,也许您可以使用您希望它在其上运行的队列(无论是主要还是后台)将任何调用的内容包装updateTableViewAnimated:在dispatch_async调用中。
Mos*_*sam 10
添加到 Jasarien 信息丰富的答案中,您需要记住UICollectionViewDiffableDataSource使用 hashable 来区分数据源中的项目
如果您的模型是一个结构体,并且您的数据源模型中有两个项目恰好具有完全相同的值,则Hashable协议将为它们生成相同的 hashValue。
Equatable协议也将返回真!,这会混淆
UICollectionViewDiffableDataSource
解决方案
Equatable,您可能希望在数据源中添加随机值,但不建议这样做,因为生成的值可能在任何巧合下都相等,如文档 * 低概率中所述,但它可能会发生 *根据范围的大小和跨度,某些具体值可能比其他值更频繁地表示。