简体   繁体   English

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

[英]class is not key value coding-compliant for the key @sum

Ok, so vote it down if you have to but I'm about ready to through something as this is making me crazy. 好的,所以如果需要的话就把它否决,但是我已经准备好要通过一些事情了,因为这使我发疯。 I have a core data application (OS X), with a couple NSTableViews (Cell Based) connected via NSArrayControllers . 我有一个core data应用程序(OS X),通过NSArrayControllers连接了几个NSTableViews (基于Cell)。 I have the Entity class' setup with some custom methods. 我有一些自定义方法的Entity类设置。 I can add, remove, edit and do all kinds of stuff with the data - all is working great. 我可以添加,删除,编辑数据并进行各种处理-一切都很好。

I decided to add a new column for a running sum and use the @sum as I have seen used. 我决定为运行中的总和添加新列,并使用@sum如我所见。 No matter what I do, I keep getting the error. 无论我做什么,我都会不断收到错误消息。

I have an Entity "Store" and another Entity "Item", they have a to-many relationship. 我有一个实体“ Store”和另一个实体“ Item”,它们有一对多的关系。 In the Item entity I have a name and price attribute. 在项目实体中,我具有名称和价格属性。

On the main window, I have two NSTableView 's controller by NSArrayController s, one for the Store and one for the Item. 在主窗口上,我有两个NSArrayControllerNSTableView控制器,一个用于存储,一个用于Item。 The content of the Item NSArrayController is controlled by the Store Controller - the selected item. 商品NSArrayController的内容由存储控制器-所选商品控制。

I added a new column to the Item NSTableView , bound it to the Item Controller and set it's model key path to @sum.price - this causes an error. 我在Item NSTableView添加了新列,将其绑定到Item Controller,并将其模型键路径设置为@ sum.price-这会导致错误。

I am probably missing something simple, any thoughts on how to do this correctly? 我可能缺少一些简单的东西,对如何正确执行此操作有任何想法吗?

Thank you. 谢谢。

--[EDIT]---- - [编辑] - -

Store NSArrayController : - Object Controller - Entity Name: Store Store NSArrayController :-对象控制器-实体名称:Store

  • ManagedObjectContext ManagedObjectContext
    • Bound to Main Controller's ManagedObjectContext 绑定到主控制器的ManagedObjectContext

Item NSArrayController : 项目NSArrayController

  • Object Controller 对象控制器

    • Entity Name: Item 实体名称:项目
  • Content Set: 内容集:

    • Bound to Store Array Controller 绑定到存储阵列控制器

    • Controller Key: Selection 控制器键:选择

    • Model Key Path:item 型号关键路径:项目

Item NSTableView : 项目NSTableView

First Column: 第一栏:

  • Bound to Item Array Controller 绑定到项目数组控制器

  • Controller Key: arrangedObjects 控制器键:rangedObjects

  • Model Key Path: name 型号密钥路径:名称

Second Column: 第二栏:

  • Similar, Model Key Path: price 相似,型号关键路径:价格

The new sum column: 新的总和列:

  • Bound to Item Array Controller 绑定到项目数组控制器

  • Controller Key: arrangedObjects 控制器键:rangedObjects

  • Model Key Path: @sum.price 模型密钥路径:@ sum.price

The error I receive is: "the entity Item is not key value coding-compliant for the key "@sum"." 我收到的错误是:“实体Item不符合键“ @sum”的编码标准。

Consider your first column. 考虑您的第一列。 It is bound to Item Controller, arrangedObjects , name . 它绑定到Item Controller, arrangedObjectsname Does each cell get an array of names? 每个单元格都有一个名称数组吗? No. Each gets a single name. 不。每个人都有一个名字。

Although that column binding is sometimes expressed as a key path like Item Controller.arrangedObjects.name , the way it actually works is that the column as a whole shows the arrangedObjects , one element per row, but name is applied to each element of that set separately. 尽管该列绑定有时表示为诸如Item Controller.arrangedObjects.name类的键路径,但实际上,该列的工作方式是该列整体上显示了arrangedObjects (每行一个元素),但name应用于该集合的每个元素分别。 So, each cell has a single name. 因此,每个单元格都有一个名称。

Now consider your new column. 现在考虑您的新专栏。 The rows again correspond to the arrangedObjects of the Item Controller, but the model key path is applied to each element individually. 这些行再次对应于Item Controller的arrangedObjects的对象,但是模型键路径分别应用于每个元素。 But the model key path contains a collection operator, @sum , which isn't appropriate for an individual element ( Item entity). 但是模型键路径包含集合运算符@sum ,它不适用于单个元素( Item实体)。 Hence the error. 因此,错误。

You could create a text field (outside of the table) which shows the sum of the price of all of the items of the selected store. 您可以创建一个文本字段(在表格外部),该文本字段显示所选商店的所有商品的价格总和。 You would bind the text field's Value binding to Item Controller, arrangedObjects , @sum.price . 你会绑定文本字段的值绑定到项目控制器, arrangedObjects@sum.price The text field works differently than the table column since it has a single thing to display. 文本字段与表格列的工作方式不同,因为它仅显示单个内容。 It really does use the result of [ItemController valueForKeyPath:@"arrangedObject.@sum.price"] . 它确实使用[ItemController valueForKeyPath:@"arrangedObject.@sum.price"] The collection operator will be applied to a collection. 集合运算符将应用于集合。

You could also bind a text field to Item Controller, selection , @sum.price to have it show the sum of the prices of the items selected in the item table. 您也可以将文本字段绑定到Item Controller, selection@sum.price以使其显示在项目表中所选项目的价格之和。

Bindings don't provide any way to get a running sum, if I understand what you mean by that (first row shows the price of the first item, second row shows the sum of the prices of the first and second items, etc.). 如果我理解您的意思,绑定将不提供任何获取总和的方法(第一行显示第一项价格,第二行显示第一项和第二项价格的总和,依此类推) 。 Such a running sum would be context dependent. 这样的总和将取决于上下文。 A given row's value would depend on the previous rows' values. 给定行的值将取决于先前行的值。 For example, sorting the table differently would mean that the running sum next to a given item would change, because the set of items before it had changed. 例如,对表进行不同的排序将意味着给定项目旁边的运行总和将发生变化,因为之前的一组项目已发生变化。 Bindings can't do that. 绑定无法做到这一点。 They don't know about position, index, or siblings. 他们不知道位置,索引或同级。


Update: 更新:

To get a running sum, you'll need to not use bindings for the column. 要获得连续的总和,您无需为该列使用绑定。 Make your view or window controller adopt NSTableViewDataSource if it doesn't already. 如果您的视图或窗口控制器尚未采用NSTableViewDataSource则使其采用它。 Then connect the dataSource outlet of the table view to it. 然后将表视图的dataSource出口连接到它。

In your data source class, implement -tableView:objectValueForTableColumn:row: . 在数据源类中,实现-tableView:objectValueForTableColumn:row: Check the column identifier . 检查列identifier For any columns other than the running sum column, return nil so it uses the value from the column bindings. 对于除运行总和列以外的任何列,返回nil以便它使用列绑定中的值。

For the running sum column, the straightforward-but-inefficient implementation would be something like: 对于运行总和列,简单但效率低下的实现将类似于:

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

You would also need a way to inform the table view when cells in the running sum column need to be reloaded (recomputed). 您还需要一种方法来通知表视图何时需要重新加载(重新计算)运行总和列中的单元格。 You would use Key-Value Observing to observe self for a change in the key path @"itemController.arrangedObjects.price" . 您将使用键值观察来观察self是否在键路径@"itemController.arrangedObjects.price"发生更改。 You would set this up in -viewDidLoad or -windowDidLoad . 您可以在-viewDidLoad-windowDidLoad Don't forget to tear it down when the controller is done. 控制器完成后,请不要忘记将其拆除。

When the change notification is delivered — ie when -observeValueForKeyPath:ofObject:change:context: is called — you would call -reloadDataForRowIndexes:columnIndexes: on the table view to indicate that all row indexes in the running sum column should be reloaded. 当发出更改通知时(即,当-observeValueForKeyPath:ofObject:change:context:被调用时),您将在表视图上调用-reloadDataForRowIndexes:columnIndexes:以指示应重新加载运行总和列中的所有行索引。

That should work but it will be horribly inefficient once you get a significant number of rows. 那应该行得通,但是一旦您获得大量的行,它将效率极低。

So, to optimize, you should cache the running sums, but you need to be careful to invalidate the cache appropriately. 因此,为了进行优化,您应该缓存运行总和,但是需要注意适当地使缓存无效。

Basically, have an instance variable like _cacheIsValid . 基本上,有一个实例变量,如_cacheIsValid Like all instance variables, it will start out zero (false) by default. 像所有实例变量一样,默认情况下它将以零(false)开头。 In -tableView:objectValueForTableColumn:row: , you'd check if it's valid. -tableView:objectValueForTableColumn:row: ,您将检查其是否有效。 If it's not, you would build it and record that it's valid. 如果不是,则将其构建并记录其有效。 Then, or if it was already valid, just return the element for the requested row. 然后,或者如果它已经有效,则只需返回所请求行的元素。

To build the cache, iterate over self.itemController.arrangedObjects computing the running sum as you go and adding each value onto the end of an array. 要构建缓存,请遍历self.itemController.arrangedObjects在运行时计算运行总和,并将每个值添加到数组的末尾。 You could use a C-style array of primitive types or an NSMutableArray of NSNumber s, as you prefer. 您可以根据需要使用基本类型的C样式数组或NSNumberNSMutableArray (The memory management for C-style arrays can be made simpler by using an NSMutableData for the buffer.) (通过使用NSMutableData作为缓冲区,可以简化C样式数组的内存管理。)

You would invalidate the cache in -observeValueForKeyPath:... , before telling the table view to reload the running sum column. 您将使-observeValueForKeyPath:...的缓存无效,然后告诉表视图重新加载运行中的sum列。

For the next step in efficiency, you might recompute the cache at that time and compare the values to the existing cache (if it's valid) as you go. 为了提高效率,您可以在那时重新计算缓存,然后将值与现有缓存(如果有效)进行比较。 Accumulate in an NSMutableIndexSet the row indexes of only those rows for which the cached running sum actually changed and use that in the call to -reloadDataForRowIndexes:columnIndexes: . 累积在NSMutableIndexSet中,仅缓存实际运行总和实际更改的行的行索引,并在对-reloadDataForRowIndexes:columnIndexes:的调用中使用该行索引。 That way, the table view only reloads the cells that actually changed. 这样,表视图仅重新加载实际更改的单元格。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM