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

Luk*_*nek 4 cocoa core-data nsarraycontroller cocoa-bindings nsorderedset

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

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

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

由于NSOrderedSet不是子类NSSet,contentSet绑定NSArrayController不适用于该关系.我发现了以下主题并试图实现那里提到的建议.

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

在提到的线程中提供的第二个建议是使用contentArray绑定并将@array操作符应用于模型密钥路径.我已经尝试过,但是当通过添加/删除对象时根本没有触及底层关系NSArrayController.

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

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

Chr*_*nle 11

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.有一些通用的解决方案可以为你做很多事情.不要使用它们.