树的 KVC 访问器模式
KVC Accessor Patterns for Trees
在 this document 中,Apple 描述了一对一和对多属性的访问器模式。对多属性涵盖索引和无序集合。
这让我想到了这个问题:
树结构是否有不同的访问器模式,或者我们应该使用(或改编)与其他类型的集合相同的访问器模式?
显然,当持有树结构的 NSArray
绑定到 NSTreeController
时,在我的模型中实现索引对多访问器并在其中设置断点没有任何效果。模型正在正确更新,例如当 adding/removing 个元素,或更改它们的顺序,但从未调用访问器实现时。
我是不是漏掉了什么?
树与数组不同,它不是一种数据结构。您可以从单个根节点开始,在这种情况下 属性 是与该节点的一对一关系,或者从顶级节点数组开始,在这种情况下 属性 是一个到-与这些节点有很多关系。树的其他级别是与那些根节点的独立关系,而不是与提供根节点的对象的关系。
NSTreeController
配置了子键路径。它使用每个节点上的关键路径来访问每个节点的子节点。如果它正在添加或删除节点,那将是通过 KVC 对父节点的子节点进行突变。 (它可能在父对象上使用 -mutableArrayValueForKeyPath:
,然后在生成的代理上使用 NSMutableArray
方法。)这应该通过父对象上的索引集合突变访问器。
您确定在正确的 class 上实现了访问器(并在其上设置了断点)吗?
除了使用 KVC 来访问和改变您的 属性,该框架别无选择。如果它们是 属性 命名的,KVC 将使用您的访问器方法。根据您实现 class 的方式,KVC 可能别无选择,只能调用您的访问器方法。例如,您可以实现一个索引集合 属性 而无需任何数组类型 getter 或 setter 或任何数组实例变量来支持它(或者它可以有一个实例变量,其名称是完整的与 属性 名称无关)。
例如,class 可以实现:
- (NSUInteger) countOfEmployess;
- (id) objectInEmployeesAtIndex:(NSUInteger)index;
- (void)insertObject:(id)anObject inEmployeesAtIndex:(NSUInteger)index;
- (void)removeObjectFromEmployeesAtIndex:(NSUInteger)index;
没有任何 -employees
或 -setEmployees:
访问器,也没有任何 employees
或 _employees
实例变量。对于名为 "employees" 的索引集合 属性,它仍然完全符合 KVC。如果给 NSTreeController
这样的节点并配置为使用 "employees" 作为子键路径,它就可以很好地操纵该节点的员工。如果没有那些访问器方法,它还能用什么?
为了更好的衡量,请务必在所有自定义 class 中实施 +accessInstanceVariablesDirectly
至 return NO
。这可以捕获拼写错误的 methods/property 名称。
在 this document 中,Apple 描述了一对一和对多属性的访问器模式。对多属性涵盖索引和无序集合。
这让我想到了这个问题:
树结构是否有不同的访问器模式,或者我们应该使用(或改编)与其他类型的集合相同的访问器模式?
显然,当持有树结构的 NSArray
绑定到 NSTreeController
时,在我的模型中实现索引对多访问器并在其中设置断点没有任何效果。模型正在正确更新,例如当 adding/removing 个元素,或更改它们的顺序,但从未调用访问器实现时。
我是不是漏掉了什么?
树与数组不同,它不是一种数据结构。您可以从单个根节点开始,在这种情况下 属性 是与该节点的一对一关系,或者从顶级节点数组开始,在这种情况下 属性 是一个到-与这些节点有很多关系。树的其他级别是与那些根节点的独立关系,而不是与提供根节点的对象的关系。
NSTreeController
配置了子键路径。它使用每个节点上的关键路径来访问每个节点的子节点。如果它正在添加或删除节点,那将是通过 KVC 对父节点的子节点进行突变。 (它可能在父对象上使用 -mutableArrayValueForKeyPath:
,然后在生成的代理上使用 NSMutableArray
方法。)这应该通过父对象上的索引集合突变访问器。
您确定在正确的 class 上实现了访问器(并在其上设置了断点)吗?
除了使用 KVC 来访问和改变您的 属性,该框架别无选择。如果它们是 属性 命名的,KVC 将使用您的访问器方法。根据您实现 class 的方式,KVC 可能别无选择,只能调用您的访问器方法。例如,您可以实现一个索引集合 属性 而无需任何数组类型 getter 或 setter 或任何数组实例变量来支持它(或者它可以有一个实例变量,其名称是完整的与 属性 名称无关)。
例如,class 可以实现:
- (NSUInteger) countOfEmployess;
- (id) objectInEmployeesAtIndex:(NSUInteger)index;
- (void)insertObject:(id)anObject inEmployeesAtIndex:(NSUInteger)index;
- (void)removeObjectFromEmployeesAtIndex:(NSUInteger)index;
没有任何 -employees
或 -setEmployees:
访问器,也没有任何 employees
或 _employees
实例变量。对于名为 "employees" 的索引集合 属性,它仍然完全符合 KVC。如果给 NSTreeController
这样的节点并配置为使用 "employees" 作为子键路径,它就可以很好地操纵该节点的员工。如果没有那些访问器方法,它还能用什么?
为了更好的衡量,请务必在所有自定义 class 中实施 +accessInstanceVariablesDirectly
至 return NO
。这可以捕获拼写错误的 methods/property 名称。