我想以编程方式将自定义类(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:
和content
方法而不是可变方法。我也尝试删除这些方法(setContent:
和content
),但它只引发异常setValue:forUndefinedKey:
[myClassInstance bind:@"content" toObject:myArrayController withKeyPath:@"arrangedObjects" options:nil];
或
[myClassInstance bind:@"content" toObject:myArrayController withKeyPath:@"content" options:nil];
我不相信每次在绑定到数组控制器时添加一行时都会重新设置整个表的数组,并且我希望使用相同类型的绑定。
答案 0 :(得分: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和 遵循相同的直接实例变量访问策略,但总是如此 返回一个可变集合代理对象而不是immutable 集合-valueForKey:会返回。它还:
- 在接收器的类中搜索名称与模式
-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:
,-insert<Key>:atIndexes:
和-remove<Key>AtIndexes:
条消息被发送到-mutableArrayValueForKey:
的原始接收方。如果 接收器的类还实现了一个名称可选的方法 匹配模式-replaceObjectIn<Key>AtIndex:withObject:
或 (在Mac OS 10.4中引入)-replace<Key>AtIndexes:with<Key>:
方法将在适当时使用以获得最佳性能。- 否则(未找到任何数组变异方法集),在接收器的类中搜索名称匹配的访问器方法 模式
-set<Key>:
。如果找到这样的方法,则每个NSMutableArray 发送到集合代理对象的消息将导致a-set<Key>:
消息被发送到-mutableArrayValueForKey:
的原始接收者。- 否则(没有找到一组数组变异方法或简单的访问方法),如果是接收者的类'
+accessInstanceVariablesDirectly
方法返回YES,在接收器的类中搜索名称与其匹配的实例变量 模式_<key>
或<key>
,按此顺序排列。如果是这样的实例变量 发现,每个NSMutableArray消息都发送到集合代理 对象将被转发到实例变量的值,即 因此,通常必须是NSMutableArray或a的实例 NSMutableArray的子类。- 否则(没有找到一组数组变异方法,简单访问器方法或实例变量),返回一个可变集合 无论如何代理对象。每个NSMutableArray消息都发送给了 集合代理对象将导致
醇>-setValue:forUndefinedKey:
消息被发送到原始接收者-mutableArrayValueForKey:
。-setValue:forUndefinedKey:
的默认实现会引发NSUndefinedKeyException,但您可以在应用程序中覆盖它。