class 与键 @sum 的键值编码不兼容
class is not key value coding-compliant for the key @sum
好的,如果必须的话,请投反对票,但我准备好通过一些事情,因为这让我发疯。我有一个 core data
应用程序 (OS X),有一对 NSTableViews
(基于单元格)通过 NSArrayControllers
连接。我使用一些自定义方法设置了 Entity class'。我可以添加、删除、编辑数据以及对数据执行各种操作——一切都很好。
我决定为 运行 总和添加一个新列,并使用我看到的 @sum
。无论我做什么,我都会不断收到错误消息。
我有一个实体 "Store" 和另一个实体 "Item",它们是一对多的关系。在 Item 实体中,我有一个名称和价格属性。
在主 window 上,我有两个 NSTableView
的 NSArrayController
控制器,一个用于商店,一个用于物品。 Item NSArrayController
的内容由 Store Controller - 所选项目控制。
我向项目 NSTableView
添加了一个新列,将其绑定到项目控制器并将其模型键路径设置为 @sum.price - 这会导致错误。
我可能遗漏了一些简单的东西,关于如何正确执行此操作有什么想法吗?
谢谢。
--[编辑]----
商店NSArrayController
:
- 对象控制器
- 实体名称:商店
- ManagedObjectContext
- 绑定到主控制器的
ManagedObjectContext
项目NSArrayController
:
对象控制器
- 实体名称:项目
内容集:
绑定到存储阵列控制器
控制器键:选择
模型键Path:item
项目NSTableView
:
第一列:
绑定到物品阵列控制器
控制器键:arrangedObjects
模型关键路径:名称
第二列:
- 类似,模型关键路径:价格
新的总和列:
绑定到物品阵列控制器
控制器键:arrangedObjects
模型关键路径:@sum.price
我收到的错误是:"the entity Item is not key value coding-compliant for the key "@sum"."
考虑你的第一列。它绑定到项目控制器,arrangedObjects
,name
。每个单元格都有一个名称数组吗?没有。每个人都有一个名字。
虽然该列绑定有时表示为像 Item Controller.arrangedObjects.name
这样的关键路径,但它实际工作的方式是整个列显示 arrangedObjects
,每行一个元素,但是 name
分别应用于该集合的每个元素。因此,每个单元格都有一个名称。
现在考虑您的新专栏。这些行再次对应于 Item Controller 的 arrangedObjects
,但模型键路径单独应用于每个元素。但是模型键路径包含一个集合运算符 @sum
,它不适用于单个元素(Item
实体)。因此错误。
您可以创建一个文本字段(在 table 之外)显示所选商店所有商品的价格总和。您可以将文本字段的值绑定绑定到项目控制器,arrangedObjects
、@sum.price
。文本字段与 table 列的工作方式不同,因为它只显示一个内容。它确实使用了 [ItemController valueForKeyPath:@"arrangedObject.@sum.price"]
的结果。集合运算符将应用于集合。
您还可以将文本字段绑定到项目控制器,selection
,@sum.price
以让它显示项目的价格总和在项目table中选择了。
绑定不提供任何方式来获得 运行 总和,如果我明白你的意思(第一行显示第一个项目的价格,第二行显示价格的总和第一项和第二项等)。这样的 运行 总和将取决于上下文。给定行的值将取决于前几行的值。例如,以不同方式对 table 排序将意味着给定项目旁边的 运行 总和会发生变化,因为它之前的项目集已发生变化。绑定不能这样做。他们不知道位置、索引或兄弟姐妹。
更新:
要获得 运行 总和,您需要不对列使用绑定。让您的视图或 window 控制器采用 NSTableViewDataSource
(如果尚未采用)。然后将 table 视图的 dataSource
出口连接到它。
在您的数据源 class 中,实施 -tableView:objectValueForTableColumn:row:
。检查列 identifier
。对于 运行 总和列以外的任何列,return nil
因此它使用列绑定中的值。
对于 运行 总和列,简单但效率低下的实现类似于:
NSRange range = NSMakeRange(0, rowIndex + 1);
NSArray* rowsToSum = [self.itemController.arrangedObjects subarrayWithRange:range];
return [rowsToSum valueForKeyPath:@"@sum.price"];
当 运行 总和列中的单元格需要重新加载(重新计算)时,您还需要一种方法来通知 table 视图。您将使用 Key-Value Observing 来观察 self
键路径 @"itemController.arrangedObjects.price"
的变化。您可以在 -viewDidLoad
或 -windowDidLoad
中进行设置。控制器完成后别忘了拆掉它。
发送更改通知时——即调用 -observeValueForKeyPath:ofObject:change:context:
时——您将在 table 视图上调用 -reloadDataForRowIndexes:columnIndexes:
以指示 [=98= 中的所有行索引] 应该重新加载总和列。
这应该可行,但一旦您获得大量行,效率就会非常低。
因此,为了优化,您应该缓存 运行 总和,但您需要注意适当地使缓存无效。
基本上,有一个像_cacheIsValid
这样的实例变量。与所有实例变量一样,默认情况下它将从零(假)开始。在 -tableView:objectValueForTableColumn:row:
中,您将检查它是否有效。如果不是,您将构建它并记录它是有效的。然后,或者如果它已经有效,只需 return 请求行的元素。
要构建缓存,请迭代 self.itemController.arrangedObjects
计算 运行 总和并将每个值添加到数组的末尾。您可以根据需要使用原始类型的 C 样式数组或 NSNumber
的 NSMutableArray
。 (对于缓冲区使用 NSMutableData
可以简化 C 风格数组的内存管理。)
在告诉 table 视图重新加载 运行 总和列之前,您可以使 -observeValueForKeyPath:...
中的缓存无效。
为了提高效率,您可能会重新计算当时的缓存,并在进行时将值与现有缓存(如果有效)进行比较。在 NSMutableIndexSet
中仅累积缓存 运行 总和实际更改的那些行的行索引,并在对 -reloadDataForRowIndexes:columnIndexes:
的调用中使用它。这样,table 视图只会重新加载实际更改的单元格。
好的,如果必须的话,请投反对票,但我准备好通过一些事情,因为这让我发疯。我有一个 core data
应用程序 (OS X),有一对 NSTableViews
(基于单元格)通过 NSArrayControllers
连接。我使用一些自定义方法设置了 Entity class'。我可以添加、删除、编辑数据以及对数据执行各种操作——一切都很好。
我决定为 运行 总和添加一个新列,并使用我看到的 @sum
。无论我做什么,我都会不断收到错误消息。
我有一个实体 "Store" 和另一个实体 "Item",它们是一对多的关系。在 Item 实体中,我有一个名称和价格属性。
在主 window 上,我有两个 NSTableView
的 NSArrayController
控制器,一个用于商店,一个用于物品。 Item NSArrayController
的内容由 Store Controller - 所选项目控制。
我向项目 NSTableView
添加了一个新列,将其绑定到项目控制器并将其模型键路径设置为 @sum.price - 这会导致错误。
我可能遗漏了一些简单的东西,关于如何正确执行此操作有什么想法吗?
谢谢。
--[编辑]----
商店NSArrayController
:
- 对象控制器
- 实体名称:商店
- ManagedObjectContext
- 绑定到主控制器的
ManagedObjectContext
- 绑定到主控制器的
项目NSArrayController
:
对象控制器
- 实体名称:项目
内容集:
绑定到存储阵列控制器
控制器键:选择
模型键Path:item
项目NSTableView
:
第一列:
绑定到物品阵列控制器
控制器键:arrangedObjects
模型关键路径:名称
第二列:
- 类似,模型关键路径:价格
新的总和列:
绑定到物品阵列控制器
控制器键:arrangedObjects
模型关键路径:@sum.price
我收到的错误是:"the entity Item is not key value coding-compliant for the key "@sum"."
考虑你的第一列。它绑定到项目控制器,arrangedObjects
,name
。每个单元格都有一个名称数组吗?没有。每个人都有一个名字。
虽然该列绑定有时表示为像 Item Controller.arrangedObjects.name
这样的关键路径,但它实际工作的方式是整个列显示 arrangedObjects
,每行一个元素,但是 name
分别应用于该集合的每个元素。因此,每个单元格都有一个名称。
现在考虑您的新专栏。这些行再次对应于 Item Controller 的 arrangedObjects
,但模型键路径单独应用于每个元素。但是模型键路径包含一个集合运算符 @sum
,它不适用于单个元素(Item
实体)。因此错误。
您可以创建一个文本字段(在 table 之外)显示所选商店所有商品的价格总和。您可以将文本字段的值绑定绑定到项目控制器,arrangedObjects
、@sum.price
。文本字段与 table 列的工作方式不同,因为它只显示一个内容。它确实使用了 [ItemController valueForKeyPath:@"arrangedObject.@sum.price"]
的结果。集合运算符将应用于集合。
您还可以将文本字段绑定到项目控制器,selection
,@sum.price
以让它显示项目的价格总和在项目table中选择了。
绑定不提供任何方式来获得 运行 总和,如果我明白你的意思(第一行显示第一个项目的价格,第二行显示价格的总和第一项和第二项等)。这样的 运行 总和将取决于上下文。给定行的值将取决于前几行的值。例如,以不同方式对 table 排序将意味着给定项目旁边的 运行 总和会发生变化,因为它之前的项目集已发生变化。绑定不能这样做。他们不知道位置、索引或兄弟姐妹。
更新:
要获得 运行 总和,您需要不对列使用绑定。让您的视图或 window 控制器采用 NSTableViewDataSource
(如果尚未采用)。然后将 table 视图的 dataSource
出口连接到它。
在您的数据源 class 中,实施 -tableView:objectValueForTableColumn:row:
。检查列 identifier
。对于 运行 总和列以外的任何列,return nil
因此它使用列绑定中的值。
对于 运行 总和列,简单但效率低下的实现类似于:
NSRange range = NSMakeRange(0, rowIndex + 1);
NSArray* rowsToSum = [self.itemController.arrangedObjects subarrayWithRange:range];
return [rowsToSum valueForKeyPath:@"@sum.price"];
当 运行 总和列中的单元格需要重新加载(重新计算)时,您还需要一种方法来通知 table 视图。您将使用 Key-Value Observing 来观察 self
键路径 @"itemController.arrangedObjects.price"
的变化。您可以在 -viewDidLoad
或 -windowDidLoad
中进行设置。控制器完成后别忘了拆掉它。
发送更改通知时——即调用 -observeValueForKeyPath:ofObject:change:context:
时——您将在 table 视图上调用 -reloadDataForRowIndexes:columnIndexes:
以指示 [=98= 中的所有行索引] 应该重新加载总和列。
这应该可行,但一旦您获得大量行,效率就会非常低。
因此,为了优化,您应该缓存 运行 总和,但您需要注意适当地使缓存无效。
基本上,有一个像_cacheIsValid
这样的实例变量。与所有实例变量一样,默认情况下它将从零(假)开始。在 -tableView:objectValueForTableColumn:row:
中,您将检查它是否有效。如果不是,您将构建它并记录它是有效的。然后,或者如果它已经有效,只需 return 请求行的元素。
要构建缓存,请迭代 self.itemController.arrangedObjects
计算 运行 总和并将每个值添加到数组的末尾。您可以根据需要使用原始类型的 C 样式数组或 NSNumber
的 NSMutableArray
。 (对于缓冲区使用 NSMutableData
可以简化 C 风格数组的内存管理。)
在告诉 table 视图重新加载 运行 总和列之前,您可以使 -observeValueForKeyPath:...
中的缓存无效。
为了提高效率,您可能会重新计算当时的缓存,并在进行时将值与现有缓存(如果有效)进行比较。在 NSMutableIndexSet
中仅累积缓存 运行 总和实际更改的那些行的行索引,并在对 -reloadDataForRowIndexes:columnIndexes:
的调用中使用它。这样,table 视图只会重新加载实际更改的单元格。