5

我有一个支持 KVO 的类(称为它Observee),它的affectedValue动态属性受属性的影响affectingValue。属性之间的依赖关系由实现+keyPathsForValuesAffectingAffectedValue方法定义。

将值设置为affectingValue通知affectedValue 已按我的预期更改, 除非 OvserveeNSObjectController. 完整示例如下:

@interface Observee : NSObject // or NSObjectController
@property (readonly, strong, nonatomic) id affectedValue;
@property (strong, nonatomic) id affectingValue;
@property (strong, nonatomic) NSArrayController *arrayController;
@end

@implementation Observee

@dynamic affectedValue;
- (id)affectedValue { return nil; }

+ (NSSet *)keyPathsForValuesAffectingAffectedValue {
  NSLog(@"keyPathsForValuesAffectingAffectedValue called");
  return [NSSet setWithObject:@"affectingValue"];
}

@end

@interface AppDelegate : NSObject <NSApplicationDelegate>
@property (strong, nonatomic) Observee *observee;
@end

@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)notification {
  self.observee = [[Observee alloc] init];
  [self.observee addObserver:self
                  forKeyPath:@"affectedValue"
                     options:NSKeyValueObservingOptionNew
                     context:NULL];
  NSLog(@"setting value to affectingValue");
  self.observee.affectingValue = @42;
}

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
  NSLog(@"affected key path = %@", keyPath);
}

@end

Observee该示例工作正常,并在派生时输出如下NSObject

keyPathsForValuesAffectingAffectedValue called
setting value to affectingValue
affected key path = affectedValue

但是当Observee派生时NSObjectController

keyPathsForValuesAffectingAffectedValue called
setting value to affectingValue

(请注意,“受影响的密钥路径 = 受影响的值”不存在。)

似乎keyPathsForValuesAffectingAffectedValue在这两种情况下都调用了它,但在后者中它是无操作的。

此外,任何涉及 (subclass of) 实例的关键路径NSObjectController都不会影响其他关键路径,例如:

@implementation SomeObject

// `someValue` won't be affected by `key.path.(snip).arrangedObjects`
+ (NSSet *)keyPathsForValuesAffectingSomeValue {
  return [NSSet setWithObject:@"key.path.involving.anNSArrayController.arrangedObjects"];
}

@end

在这种情况下,如何声明关键路径之间的依赖关系?而且,为什么这整件事会发生?

(是的,我知道will/didChangeValueForKey:和朋友们,但是用(另一个)setter 包裹每一个影响关键路径是可怕的,我想避免它。)

4

1 回答 1

6

NSController及其子类充满了 KVO 的“黑魔法”和意想不到的行为。(再举一个例子,它们不尊重某些 KVO 选项NSKeyValueObservingOptionPrior,如 它们的存在主要是为了支持 Cocoa 绑定。尽管乍一看绑定可能看起来只是 KVO 之上的语法糖,但您可以看到(通过覆盖绑定到对象的 KVO 支持方法并在其中设置断点)实际上还有很多事情要做而不是一个简单的 KVO 观察。

向 Apple 提交错误,以增加他们修复(或至少记录)此类问题/行为的可能性。

于 2013-06-17T13:57:36.393 回答