objective-c - 类别对键@sum的键值编码不兼容

标签 objective-c cocoa core-data

好的,所以如果需要的话就把它否决,但是我已经准备好要通过一些事情了,因为这使我发疯。我有一个core data应用程序(OS X),通过NSTableViews连接了几个NSArrayControllers(基于单元)。我有一些自定义方法的Entity类设置。我可以添加,删除,编辑数据并进行各种处理-一切都很好。

我决定为运行总和添加新列,并使用@sum,如我所见。无论我做什么,我都会不断收到错误消息。

我有一个实体“ Store”和另一个实体“ Item”,它们有一对多的关系。在项目实体中,我具有名称和价格属性。

在主窗口中,我有两个NSTableViewNSArrayController控制器,一个用于存储,一个用于物料。项目NSArrayController的内容由存储控制器-所选项目控制。

我在Item NSTableView中添加了新列,将其绑定到Item Controller,并将其模型键路径设置为@ sum.price-这会导致错误。

我可能缺少一些简单的东西,对如何正确执行此操作有任何想法吗?

谢谢。

- [编辑] - -

商店NSArrayController
-对象控制器
   -实体名称:商店


ManagedObjectContext

绑定到主控制器的ManagedObjectContext



项目NSArrayController


对象控制器


实体名称:项目

内容集:


绑定到存储阵列控制器
控制器键:选择
型号关键路径:项目



项目NSTableView

第一栏:


绑定到项目数组控制器
控制器键:rangedObjects
型号密钥路径:名称


第二栏:


相似,型号关键路径:价格


新的总和列:


绑定到项目数组控制器
控制器键:rangedObjects
模型密钥路径:@ sum.price


我收到的错误是:“实体Item不符合键“ @sum”的编码标准。

最佳答案

考虑您的第一列。它绑定到项目控制器arrangedObjectsname。每个单元格都有一个名称数组吗?不。每个人都有一个名字。

尽管有时将列绑定表示为像Item Controller.arrangedObjects.name这样的键路径,但实际上它的工作方式是该列整体上显示arrangedObjects,每行一个元素,但是name应用于该行的每个元素单独设置。因此,每个单元格都有一个名称。

现在考虑您的新专栏。这些行再次对应于Item Controller的arrangedObjects,但是模型键路径分别应用于每个元素。但是模型键路径包含集合运算符@sum,它不适用于单个元素(Item实体)。因此,错误。

您可以创建一个文本字段(在表格外部),该文本字段显示所选商店的所有商品的价格总和。您可以将文本字段的“值”绑定绑定到项目控制器arrangedObjects@sum.price。文本字段与表格列的工作方式不同,因为它仅显示单个内容。它确实确实使用了[ItemController valueForKeyPath:@"arrangedObject.@sum.price"]的结果。集合运算符将应用于集合。

您还可以将文本字段绑定到项目控制器selection@sum.price,以使其显示项目表中所选项目的价格总和。

如果我理解您的意思,绑定不会提供任何方式来获得连续的总和(第一行显示第一项目的价格,第二行显示第一项目和第二项目的价格之和,等等) 。这样的总和将取决于上下文。给定行的值将取决于先前行的值。例如,对表进行不同的排序将意味着给定项目旁边的运行总和将发生变化,因为之前的一组项目已发生变化。绑定无法做到这一点。他们不知道位置,索引或同级。



更新:

要获得连续的总和,您无需为该列使用绑定。如果您的视图或窗口控制器尚未采用NSTableViewDataSource,请使其采用。然后将表视图的dataSource出口连接到它。

在您的数据源类中,实现-tableView:objectValueForTableColumn:row:。检查列identifier。对于除运行总和列以外的任何列,请返回nil,以便它使用列绑定中的值。

对于运行总和列,简单但效率低下的实现将类似于:

NSRange range = NSMakeRange(0, rowIndex + 1);
NSArray* rowsToSum = [self.itemController.arrangedObjects subarrayWithRange:range];
return [rowsToSum valueForKeyPath:@"@sum.price"];


您还需要一种方法来通知表格视图何时需要重新加载(重新计算)运行总和列中的单元格。您将使用键值观察来观察self键路径@"itemController.arrangedObjects.price"中的变化。您可以在-viewDidLoad-windowDidLoad中进行设置。控制器完成后,请不要忘记将其拆除。

发出更改通知后-即调用-observeValueForKeyPath:ofObject:change:context:-您将在表视图上调用-reloadDataForRowIndexes:columnIndexes:以指示应重新加载运行总和列中的所有行索引。

那应该行得通,但是一旦您获得大量的行,它将效率极低。

因此,为了进行优化,您应该缓存运行总和,但是需要注意适当地使缓存无效。

基本上,有一个实例变量,例如_cacheIsValid。像所有实例变量一样,默认情况下它将以零(false)开头。在-tableView:objectValueForTableColumn:row:中,您将检查其是否有效。如果不是,则将其构建并记录其有效。然后,或者如果它已经有效,则只需返回所请求行的元素。

要构建缓存,请遍历self.itemController.arrangedObjects并计算运行总和,并将每个值添加到数组的末尾。您可以根据需要使用基本样式类型的C样式数组或NSMutableArrayNSNumber。 (可以通过将NSMutableData用于缓冲区来简化C样式数组的内存管理。)

在告诉表视图重新加载运行总和列之前,您将使-observeValueForKeyPath:...中的缓存无效。

为了提高效率,您可以在那时重新计算缓存,然后将值与现有缓存(如果有效)进行比较。在NSMutableIndexSet中仅累积那些实际运行的总和发生更改的行的行索引,并在对-reloadDataForRowIndexes:columnIndexes:的调用中使用该行索引。这样,表视图仅重新加载实际更改的单元格。

关于objective-c - 类别对键@sum的键值编码不兼容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28622617/

相关文章:

ios - 没有找到适合核心数据迁移的映射模型

objective-c - 在 Debug模式下未检测到垃圾值

objective-c - 如何向 XCode 6 中的 UISlider 添加渐变色?

objective-c - iOS 8 删除今日扩展

cocoa - 如何设置图像透视

iphone - 核心数据的 ActiveRecord

java - Java至 objective-c :Indexof()

cocoa - "coupled"NSWindows

objective-c - 应用程序、辅助工具通讯

swift - NSFetchedResultsControllerDelegate 和 Swift 3 - 不调用 didChange 方法