UITableViewDiffableDataSource 能否检测到项目已更改?
Can UITableViewDiffableDataSource detect an item changed?
(在下面与@AndreasOetjen 讨论后重写了这个问题。感谢他的评论。)
我 运行 遇到了将 UITableView
与可比较数据源一起使用的问题。在我的应用程序中,当用户修改一个项目时,它可能会更改显示在同一 table 视图中的另一个项目。问题是,在我创建并应用包含两个项目的新值的新快照后,间接更改的项目的 UI 没有更新。
一开始我以为diffable data source可以在不同的快照中检测到一个item的值变化。例如,它可能以这种方式工作:如果它发现两个快照都包含相同的项目(即两个快照中的项目具有相同的哈希值),它会比较它们的值并在 table 视图中更新该项目的行,如果值变了。然而,我后来意识到它可能不会那样工作,因为 diffable 数据源没有定义任何 API 来获取和比较项目值(我最初的想法是它使用 description
computed 属性 和 ==
操作,但现在我相信这不是真的)。
所以我目前的理解是可区分数据源使用项目的散列来检测项目顺序变化(即插入的新项目,旧项目仍然存在等),而不是物品价值变化(即旧物品仍然存在,但其价值发生了变化)。如果这个理解是正确的,那么问题来了:如何使用diffable data source来实现下面的场景?
- 一个项目有多个属性。一个 属性(我们称它为 属性 A)在 UI 中显示,但不用于生成哈希。
- 该项目存在于旧快照和新快照中,但其 属性A 发生了变化。所以它的 UI 需要更新。
在旧的UITableView
API中,这可以通过调用reloadRows()
或reloadData()
来实现。但是如何使用 diffable 数据源呢?
更新:
在花时间做实验和解决问题后,我认为上述问题的理解是错误的。请在下面查看我的回答。我相信这解释了 diffable 数据源的工作原理。我希望它能帮助其他有同样困惑的人。我很高兴被证明是错误的。真的。所以如果你有不同的想法,请留下你的答案。
我对你的最后一句话有点困惑:你写 my item is an enum with associated values of reference type,但在你上面的例子中你使用 struct Book
,这是一个值类型。不管怎样,在任何情况下都必须牢记以下几点:
哈希就是 "object" 身份。这只是一种改进身份比较,折叠等的捷径
如果您提供自定义哈希实现,则两个对象 a
和 b
的行为方式必须 a == b
也暗示 hash(a) == hash(b)
(反之亦然几乎总是如此,但可能存在冲突 - 特别是弱哈希算法 - 当情况并非如此时)。
因此,如果您只散列 title
和 author
,那么您必须以一种只比较 title
和 author
的方式实现比较运算符.然后,如果 notes
发生变化,无论是数据源还是任何主体都不会检测到身份的变化。
UITableViewDiffableDataSource
是一种促进视图和数据源之间insert/delete语句同步的手段。如果你得到这个
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (3) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 2 deleted).'
那么 diffable 数据源就是你的朋友。
希望对您有所帮助。
经过将近一天的毫无头绪的实验,我相信我弄清楚了 diffable data source 的工作原理并基于这种理解解决了我的问题(事实证明我最初的想法几乎是正确的)。
可区分数据源使用项目哈希来标识项目。 对于同时存在于旧快照和新快照中的相同项目,diffable 数据源通过对其旧值和新值执行“==”操作来检查项目是否更改。
一旦弄清楚,它看起来是非常明显和简单的方法。但它是如此基础,我无法理解为什么没有在任何地方明确提及它。
所以,回答我原来的问题,是的,可区分数据源可以检测项目值的变化。也就是说,当项目值是引用类型时,它变得很棘手 and/or 行中显示的文本是该对象引用的对象的属性(例如,Core Data 中的关系)等
另一个注意事项。无论是使用整个项目结构还是仅使用其中的一部分来生成项目哈希都无关紧要,只要它标识项目即可。我更喜欢只使用真正识别它的项目的基本部分。
(在下面与@AndreasOetjen 讨论后重写了这个问题。感谢他的评论。)
我 运行 遇到了将 UITableView
与可比较数据源一起使用的问题。在我的应用程序中,当用户修改一个项目时,它可能会更改显示在同一 table 视图中的另一个项目。问题是,在我创建并应用包含两个项目的新值的新快照后,间接更改的项目的 UI 没有更新。
一开始我以为diffable data source可以在不同的快照中检测到一个item的值变化。例如,它可能以这种方式工作:如果它发现两个快照都包含相同的项目(即两个快照中的项目具有相同的哈希值),它会比较它们的值并在 table 视图中更新该项目的行,如果值变了。然而,我后来意识到它可能不会那样工作,因为 diffable 数据源没有定义任何 API 来获取和比较项目值(我最初的想法是它使用 description
computed 属性 和 ==
操作,但现在我相信这不是真的)。
所以我目前的理解是可区分数据源使用项目的散列来检测项目顺序变化(即插入的新项目,旧项目仍然存在等),而不是物品价值变化(即旧物品仍然存在,但其价值发生了变化)。如果这个理解是正确的,那么问题来了:如何使用diffable data source来实现下面的场景?
- 一个项目有多个属性。一个 属性(我们称它为 属性 A)在 UI 中显示,但不用于生成哈希。
- 该项目存在于旧快照和新快照中,但其 属性A 发生了变化。所以它的 UI 需要更新。
在旧的UITableView
API中,这可以通过调用reloadRows()
或reloadData()
来实现。但是如何使用 diffable 数据源呢?
更新:
在花时间做实验和解决问题后,我认为上述问题的理解是错误的。请在下面查看我的回答。我相信这解释了 diffable 数据源的工作原理。我希望它能帮助其他有同样困惑的人。我很高兴被证明是错误的。真的。所以如果你有不同的想法,请留下你的答案。
我对你的最后一句话有点困惑:你写 my item is an enum with associated values of reference type,但在你上面的例子中你使用 struct Book
,这是一个值类型。不管怎样,在任何情况下都必须牢记以下几点:
哈希就是 "object" 身份。这只是一种改进身份比较,折叠等的捷径
如果您提供自定义哈希实现,则两个对象 a
和 b
的行为方式必须 a == b
也暗示 hash(a) == hash(b)
(反之亦然几乎总是如此,但可能存在冲突 - 特别是弱哈希算法 - 当情况并非如此时)。
因此,如果您只散列 title
和 author
,那么您必须以一种只比较 title
和 author
的方式实现比较运算符.然后,如果 notes
发生变化,无论是数据源还是任何主体都不会检测到身份的变化。
UITableViewDiffableDataSource
是一种促进视图和数据源之间insert/delete语句同步的手段。如果你得到这个
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections. The number of sections contained in the table view after the update (3) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 2 deleted).'
那么 diffable 数据源就是你的朋友。
希望对您有所帮助。
经过将近一天的毫无头绪的实验,我相信我弄清楚了 diffable data source 的工作原理并基于这种理解解决了我的问题(事实证明我最初的想法几乎是正确的)。
可区分数据源使用项目哈希来标识项目。 对于同时存在于旧快照和新快照中的相同项目,diffable 数据源通过对其旧值和新值执行“==”操作来检查项目是否更改。
一旦弄清楚,它看起来是非常明显和简单的方法。但它是如此基础,我无法理解为什么没有在任何地方明确提及它。
所以,回答我原来的问题,是的,可区分数据源可以检测项目值的变化。也就是说,当项目值是引用类型时,它变得很棘手 and/or 行中显示的文本是该对象引用的对象的属性(例如,Core Data 中的关系)等
另一个注意事项。无论是使用整个项目结构还是仅使用其中的一部分来生成项目哈希都无关紧要,只要它标识项目即可。我更喜欢只使用真正识别它的项目的基本部分。