3

我想以编程方式将自定义类 ( MyClass) 数组绑定到数组控制器 ( NSArrayController),并将其内容绑定到另一个数组 ( modelArray)。MyClass显示数组的内容,如NSTableView.

我的问题是:如何以调用可变数组的方法的方式创建此绑定,即方法

-(void) insertObject:(id)object inContentAtIndex:(NSUInteger)index
-(void) removeObjectFromContent:(id) object

(1)如果我这样绑定,上面的方法都被调用了但是控制器的内容不再绑定到modelArray(明显)

[myArrayController bind:@"contentArray" toObject:myClassInstance withKeyPath:@"content" options:nil];

(2) 如果我以这些方式绑定,则只调用setContent:andcontent方法而不调用可变方法。我也尝试删除这些方法(setContent:content),但它只会引发异常setValue:forUndefinedKey:

[myClassInstance bind:@"content" toObject:myArrayController withKeyPath:@"arrangedObjects" options:nil];

或者

[myClassInstance bind:@"content" toObject:myArrayController withKeyPath:@"content" options:nil];

我不相信每次在绑定到数组控制器时添加一行时都会重新设置整个表的数组,我希望有相同的绑定。

4

1 回答 1

2

您遇到的问题与键值编码如何处理数组值有关。KVC 没有具体类型的概念,所以当你通过 KVC 访问一个数组值时,它无法知道返回的数组是可变的。它必须假设最坏的情况(即数组是不可变的)。它通常处理这个问题的方式是使用一个代理对象,它的作用类似于 NSMutableArray,但在幕后它需要你假定的不可变数组,制作一个可变副本,改变副本,然后使用 setter 将整个事情推回。(这是您所看到的行为——整个数组被替换而不是被原地变异。)

控制此功能的方法是- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key。该方法可能会发生很多事情,我将在下面粘贴此方法的标题注释以提供完整的故事,但长话短说,如果您希望 NSArrayController 改变您的可变数组,最简单的方法是将此覆盖添加到出售modelArray属性的类中:

- (NSMutableArray *)mutableArrayValueForKey:(NSString *)key
{
    if ([@"modelArray" isEqual: key])
    {
        // We know this is mutable, even if KVC doesn't!
        return self.modelArray;
    }
    return [super mutableArrayValueForKey:key];
}

更长的故事是,KVC 在试图弄清楚如何处理集合突变时会寻找一系列的东西。它们在 中进行了详细解释NSKeyValueCoding.h。这些是 的评论mutableArrayValueForKey:

给定一个标识有序对多关系的键,返回一个可变数组,该数组提供对相关对象的读写访问。添加到可变数组的对象将与接收者相关,而从可变数组中删除的对象将变得无关。

此方法的默认实现识别与 -valueForKey:'s 相同的简单访问器方法和数组访问器方法,并遵循相同的直接实例变量访问策略,但始终返回可变集合代理对象,而不是 -valueForKey: 的不可变集合:会回来的。它也是:

  1. 在接收者的类中搜索名称与模式匹配的方法-insertObject:in<Key>AtIndex:-removeObjectFrom<Key>AtIndex:(对应于 NSMutableArray 类定义的两个最原始的方法),以及(在 Mac OS 10.4 中引入)-insert<Key>:atIndexes:以及和 -remove<Key>AtIndexes:(对应于-[NSMutableArray insertObjects:atIndexes:]-[NSMutableArray removeObjectsAtIndexes:])。如果找到至少一种插入方法和至少一种删除方法,则发送到集合代理对象的每个 NSMutableArray 消息将导致 -insertObject:in<Key>AtIndex:发送到的原始接收者的消息-removeObjectFrom<Key>AtIndex:的某种组合。如果接收者的类还实现了一个名称与模式匹配的可选方法,或者(在 Mac OS 10.4 中引入)-insert<Key>:atIndexes:-remove<Key>AtIndexes:-mutableArrayValueForKey:-replaceObjectIn<Key>AtIndex:withObject:-replace<Key>AtIndexes:with<Key>:将在适当时使用该方法以获得最佳性能。
  2. 否则(未找到数组变异方法集),在接收者的类中搜索名称与模式匹配的访问器方法-set<Key>:。如果找到这样的方法,则发送到集合代理对象的每个 NSMutableArray 消息都会导致将 -set<Key>:消息发送到-mutableArrayValueForKey:.
  3. 否则(没有找到一组数组变异方法或简单的访问器方法),如果接收者的类的 +accessInstanceVariablesDirectly方法返回 YES,则在接收者的类中搜索名称与模式匹配的实例变量,_<key>或者<key>按该顺序。如果找到这样的实例变量,发送到集合代理对象的每个 NSMutableArray 消息将被转发到实例变量的值,因此它通常必须是 NSMutableArray 的实例或 NSMutableArray 的子类。
  4. 否则(没有找到一组数组变异方法、简单访问器方法或实例变量),无论如何都会返回一个可变集合代理对象。每个发送到集合代理对象的 NSMutableArray 消息都会导致将-setValue:forUndefinedKey: 消息发送到 -mutableArrayValueForKey:. 的默认实现-setValue:forUndefinedKey:引发 NSUndefinedKeyException,但您可以在应用程序中覆盖它。
于 2013-06-18T12:21:28.297 回答