keyPathsForValuesAffectingValueForKey:它是否以递归方式触发更改?

时间:2013-06-27 14:59:51

标签: objective-c key-value-observing

我正在阅读Apple的Key-Value Observing指南,并没有详细解释一点。

我的问题是:说我的name属性取决于firstNamelastName,我还有另一个依赖group的属性name }和gender

按照指南,我写了这个

+ (NSSet *)keyPathsForValuesAffectingName {
    return [NSSet setWithObjects:@"lastName",@"firstName",nil];
}

group编写相应的方法时,我可以像这样写

+ (NSSet *)keyPathsForValuesAffectingGroup {
    return [NSSet setWithObjects:@"name",@"gender",nil];
}

或者我必须添加所有相关属性

+ (NSSet *)keyPathsForValuesAffectingGroup {
    return [NSSet setWithObjects:@"firstName",@"lastName",@"gender",nil];
}

请注意,groupname都是计算的,只读属性。

3 个答案:

答案 0 :(得分:2)

如果您的问题意味着......

  

可以keyPathsForValuesAffecting<key>链接到通过几个相关属性间接影响密钥吗?

...然后答案是肯定的。

编辑:keyPathsForValuesAffectingValueForKey: Apple's documentation确认支持间接相关通知。

您的上一条评论似乎表明您希望在直接更改ivar时发送KVO通知(间接或非间接)。事实并非如此。 KVO依赖于使用正确的setter或通过发送will/didChangeValueForKey:

手动宣布更改

答案 1 :(得分:0)

我很确定,这会有效,因为很难让它无效。

让我们想象一下,你有三个属性的外部(=不同对象)观察者。

会发生什么:

一个。 KVO的开门是消息didChangeValueForKey:观察对象。如果您已打开自动KVO,则在调用密钥的setter时会自动发送此消息。 (这是在动态生成的子类中完成的,它会覆盖setter。)

B中。然后触发KVO代码,它在语义上看起来像这样:(它只是为了支持键而不是键路径而简化。)

NSSet *observers = kvoBucket[key];
for( id observer in observers )
{
    [observer observeValue:[self valueForKey:key] forKeyPath:key …]
}

℃。通过影响键,必须有第二个循环,通知依赖属性的变化。 (我假设,这个列表是在类'对象的初始化或添加观察时生成的。)

// Inform observers
NSSet *observers = kvoBucket[key];
for( id observer in observers )
{
    [observer observeValue:[self valueForKey:key] forKeyPath:key …]
}

// Scan for affected properties
NSSet *keyOfaffectedProperties = affectedPropertiesBucket[key];
for( NSString *key in keyOfaffectedProperties )
{
    // trigger kvo for affected property
}

不要让我们坐在开发人员的椅子上。他可以将第一个循环复制到第二个循环中。在这种情况下,它将无法正常工作。但这是重复的代码。 (而且真正的代码肯定会更复杂。)他为什么要这样做?我们每个人都会说:我已经有了这个代码!让我们再次使用它:

- (void)informOberserversForChangeOfKey:(NSString*)key
// Inform observers
NSSet *observers = kvoBucket[key];
for( id observer in observers )
{
    [observer observeValue:[self valueForKey:key] forKeyPath:key …]
}

// Scan for affected properties
NSSet *keyOfaffectedProperties = affectedPropertiesBucket[key];
for( NSString *keyOfAffectedProperty in keyOfaffectedProperties )
{
    [self informObserversForChangeOfKey:keyOfAffectedProperty];
}

如果没有优化,这使得递归不可能或不方便,它应该工作。我敢打赌它有效 - 但只有少量的钱。 ; - )

答案 2 :(得分:0)

这里的大多数人都有正确的想法,但为了确认这一点,我已经设置了一个测试项目,其中包含与我的问题中提到的完全相同的代码。

结果:它适用于两种方式。