5

所有那些“NSOrderedSet 是后来添加的,因此不必与其他组件配合得很好”的错误让我抓狂……</p>

https://twitter.com/kubanekl/status/413447039855640576

我有两个托管对象和它们之间的有序 1:N 关系,它由NSOrderedSet. 我想使用 a 来管理这种关系NSArrayController,以便从它提供的功能中获利(选择管理、内容绑定、与视图等的绑定NSTableView)。

由于NSOrderedSet不是 的子类NSSet,因此contentSet绑定NSArrayController不适用于该关系。我找到了以下线程并尝试实施那里提到的建议。

第一个建议是使用contentArray绑定和值转换器将有序集动态转换为数组。此解决方案的问题是每次进行更改时都会重新分配内容,这不是我想要的。

提到的线程中提供的第二个建议是使用contentArray绑定并将@array运算符应用于模型键路径。我已经尝试过了,但是通过NSArrayController.

contentSet我发现的另一个选项是使用带有绑定的排序描述符。这将需要使关系无序以使contentSet绑定工作并引入一个新属性,特别是用于管理订单。这将进一步需要一个自定义的排序机制来实现,它会弄乱模型。老实说,我想避免这种解决方案。

我的问题很清楚:有没有办法使用 来管理有序的核心数据关系NSArrayController?如果是这样,哪种方法是尽可能减少疼痛的最佳方法?

4

1 回答 1

11

NSArrayController 不支持有序关系确实很可悲。作为绑定技术的敏锐观察者,我发现苹果似乎已经“放弃”了它而没有说什么是次优的。Apple 在绑定方面引入的最后一个值得注意的变化是 NSTreeController 错误修复。我相信 10.6/10.7 就是这样。看来苹果不想再碰绑定技术了。我不知道为什么,因为绑定有时真的很棒。它们可以是“90% 的解决方案”。在原型制作期间,这很好。我在有意义的地方使用绑定,并且让 NSArrayController 支持有序关系会很棒。

已经提到的大多数解决方案都不是真正的解决方案。但这取决于。这是需要考虑的事情:

  1. 如果您计划支持 iCloud,那么您无论如何都不应该/不能使用有序关系,因为 iCloud 上的 Core Data 不支持它们。
  2. 由于有序关系是相当新的,而且对有序对象集合的需求早在它们之前就已经存在,所以 Core Data 中必须有一种方法来模拟有序关系。您已经指出 99.9% 的 Core Data 饮食世界在有序关系可用之前所做的事情:按附加属性排序。您已经指出这会弄乱模型,但我不同意:确实,您必须向模型添加一个附加属性,该属性不一定“代表”真实的模型数据。但是你计划在你的模型中有多少有序的关系呢?通常每个应用程序没有那么多。尽管感觉有点脏,但很多人在 Core Data 的至少三个主要版本(10.4、10.5 和 10.6)中已经这样做了。即使在今天,这个解决方案也用于向后兼容或者如果你想使用 iCloud。这是一个“务实”的解决方案。不是很好,但很务实。也请不要:即使您使用有序关系,对象的顺序也必须存储在某个地方。如果您使用的是 SQLite 存储,那么具有有序关系会导致 NSSQLiteStore 为您创建一个附加列。该列的名称为:Z_FOK_$RELATIONSHIPNAME。因此,通过使用有序关系,无论如何您只是在做一些在幕后为您完成的事情。这意味着从纯技术角度来看,如果您使用有序关系或附加属性,这并不重要。潜在的技术问题保持不变。有序的关系并不神奇。这是一个“务实”的解决方案。不是很好,但很务实。也请不要:即使您使用有序关系,对象的顺序也必须存储在某个地方。如果您使用的是 SQLite 存储,那么具有有序关系会导致 NSSQLiteStore 为您创建一个附加列。该列的名称为:Z_FOK_$RELATIONSHIPNAME。因此,通过使用有序关系,无论如何您只是在做一些在幕后为您完成的事情。这意味着从纯技术角度来看,如果您使用有序关系或附加属性,这并不重要。潜在的技术问题保持不变。有序的关系并不神奇。这是一个“务实”的解决方案。不是很好,但很务实。也请不要:即使您使用有序关系,对象的顺序也必须存储在某个地方。如果您使用的是 SQLite 存储,那么具有有序关系会导致 NSSQLiteStore 为您创建一个附加列。该列的名称为:Z_FOK_$RELATIONSHIPNAME。因此,通过使用有序关系,无论如何您只是在做一些在幕后为您完成的事情。这意味着从纯技术角度来看,如果您使用有序关系或附加属性,这并不重要。潜在的技术问题保持不变。有序的关系并不神奇。即使您使用有序关系,对象的顺序也必须存储在某个地方。如果您使用的是 SQLite 存储,那么具有有序关系会导致 NSSQLiteStore 为您创建一个附加列。该列的名称为:Z_FOK_$RELATIONSHIPNAME。因此,通过使用有序关系,无论如何您只是在做一些在幕后为您完成的事情。这意味着从纯技术角度来看,如果您使用有序关系或附加属性,这并不重要。潜在的技术问题保持不变。有序的关系并不神奇。即使您使用有序关系,对象的顺序也必须存储在某个地方。如果您使用的是 SQLite 存储,那么具有有序关系会导致 NSSQLiteStore 为您创建一个附加列。该列的名称为:Z_FOK_$RELATIONSHIPNAME。因此,通过使用有序关系,无论如何您只是在做一些在幕后为您完成的事情。这意味着从纯技术角度来看,如果您使用有序关系或附加属性,这并不重要。潜在的技术问题保持不变。有序的关系并不神奇。因此,通过使用有序关系,无论如何您只是在做一些在幕后为您完成的事情。这意味着从纯技术角度来看,如果您使用有序关系或附加属性,这并不重要。潜在的技术问题保持不变。有序的关系并不神奇。因此,通过使用有序关系,无论如何您只是在做一些在幕后为您完成的事情。这意味着从纯技术角度来看,如果您使用有序关系或附加属性,这并不重要。潜在的技术问题保持不变。有序的关系并不神奇。
  3. 如果您打算使用“附加属性”解决方案,请注意您必须大量调整此属性的值:每次用户通过拖放更改顺序时,您都必须修改属性的值。这看起来很浪费,但实际上并非如此。更糟糕的情况是:将第 0 行的对象与最后可能行的对象交换的用户只会导致 2 次属性更改。表示可以通过拖放在表视图中进行的任何更改所需的更改的简单解决方案的复杂性是 O(n),其中 n 是选定行的数量。这真的不是那么糟糕,因为用户通常不会一次重新排序 10000000 行,即使那样,那里也有更智能的算法,它们并不难实现。
  4. 如果你正在寻找最干净的解决方案,你应该继承 NSArrayController 并自己添加一个“orderedContentSet”绑定。您可以通过阅读 Cocoa Bindings Programming 主题指南了解如何做到这一点。该指南包含一个示例:https ://developer.apple.com/library/mac/documentation/cocoa/conceptual/CocoaBindings/Concepts/HowDoBindingsWork.html (清单 2)。这样做的坏处是您将 NSArrayController 子类化,这通常是不可行的。许多人倾向于继承 NSArrayController 的原因并不能证明继承它是合理的。在这种情况下,如果您想使用最干净的解决方案,则继承 NSArrayController 是合理的。
  5. 对于 3. 有一些通用的解决方案可以为你做很多事情。不要使用它们。
于 2013-12-22T12:54:31.827 回答