使用NSArrayController管理有序核心数据关系

时间:2013-12-21 12:33:54

标签: cocoa core-data cocoa-bindings nsarraycontroller nsorderedset

  

所有这些“NSOrderedSet后来被添加,因此不必与其他组件一起玩”错误让我发疯...

     

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

我有两个托管对象和它们之间有序的1:N关系,它由NSOrderedSet的实例(或更精确的子类)支持。我想使用NSArrayController来管理这种关系,以便从它提供的功能中获益(选择管理,内容绑定,绑定到NSTableView等视图。)

由于NSOrderedSet不是NSSet的子类,contentSet的{​​{1}}绑定不适用于该关系。我找到following thread并尝试实施那里提到的建议。

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

提到的主题中提供的第二个建议是使用contentArray绑定并将contentArray运算符应用于模型键路径。我试过了,但是当通过@array添加/删除对象时,基本关系根本没有触及

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

我的问题非常清楚:有没有办法使用contentSet来管理有序的核心数据关系?如果是这样,哪种方法尽可能少引起疼痛?

1 个答案:

答案 0 :(得分:10)

NSArrayController不支持有序关系确实令人非常难过。作为绑定技术的敏锐观察者,我发现苹果似乎没有说什么就“放弃”了它。 Apple引入的关于绑定的最后一个值得注意的变化是NSTreeController错误修复。那是我相信的10.6 / 10.7。苹果似乎不想再接触绑定技术了。我不知道为什么因为绑定有时真的很棒。它们可以是“90%解决方案”。在原型设计期间,这很好。我正在使用有意义的绑定,并且使用有序关系支持的NSArrayController会很棒。

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

  1. 如果您计划支持iCloud,那么您不应该/不能使用有序关系,因为iCloud上的Core Data不支持它们。
  2. 由于有序关系是相当新的,并且在它们之前很久就存在对有序对象集合的需求,因此Core Data中必须有一种模仿有序关系的方法。您已经指出了有序关系可用之前99.9%的核心数据吃世界所做的事情:按其他属性排序。你已经指出这会弄乱模型,但我不同意:你必须在你的模型中添加一个额外的属性,它不一定“代表”真正的模型数据。但是你计划在你的模型中有多少有序关系?通常每个应用程序没有那么多。即使感觉有点脏,这也是很多人至少在三个主要版本的Core Data(10.4,10.5和10.6)上所做的。即使在今天,此解决方案仍用于向后兼容,或者如果您想使用iCloud。这是一个“务实”的解决方案。不是一个好的,但务实。另请不要:即使您使用有序关系,您的对象的顺序也必须存储在某处。如果您使用的是SQLite存储,那么具有有序关系会导致NSSQLiteStore为您创建一个额外的列。该列的名称为:Z_FOK_ $ RELATIONSHIPNAME。因此,通过使用有序的关系,你只是做了一些事情,无论如何都是为你做的事情。这意味着如果您使用有序关系或其他属性,从纯技术角度来看并不重要。潜在的技术问题保持不变。有序的关系并不神奇。
  3. 如果您打算使用“附加属性”解决方案,请注意您必须经常调整此属性的值:每次用户通过拖放更改ordere时,您必须修改值属性。这似乎很浪费但实际上并非如此。即使是更糟糕的情况:在第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.有一些通用的解决方案可以为你做很多事情。不要使用它们。