Objective c KVO:+;KeyPathForvaluesAffecting<;键>;不';不使用NSObjectController的(子类)

Objective c KVO:+;KeyPathForvaluesAffecting<;键>;不';不使用NSObjectController的(子类),objective-c,cocoa,key-value-observing,nsarraycontroller,nsobjectcontroller,Objective C,Cocoa,Key Value Observing,Nsarraycontroller,Nsobjectcontroller,我有一个KVO-able类(称之为observeee),它affectedValue动态属性受affectingValue属性的影响。属性之间的依赖关系是通过实现+keypathsforvaluesafectingaffectedvalue方法定义的 将值设置为affectingValue会通知affectedValue已按预期更改,除非Ovservee是NSObjectController的子类。完整示例如下: @interface Observee : NSObject // or NSOb

我有一个KVO-able类(称之为
observeee
),它
affectedValue
动态属性受
affectingValue
属性的影响。属性之间的依赖关系是通过实现
+keypathsforvaluesafectingaffectedvalue
方法定义的

将值设置为
affectingValue
会通知
affectedValue
已按预期更改,除非
Ovservee
NSObjectController
的子类。完整示例如下:

@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
但是当
observeee
派生
NSObjectController
时:

keyPathsForValuesAffectingAffectedValue called
setting value to affectingValue
(请注意,“受影响的键路径=受影响的值”不存在。)

似乎在这两种情况下都调用了
keypathsforvaluesafectingaffectedvalue
,但在后者中它不是op

此外,任何涉及NSObjectController的(子类)
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:和friends,但是用(另一个)setter封装每个影响的关键路径是很糟糕的,我想避免它。)

NSController
及其子类充满了KVO“黑魔法”和意外行为。(另一个例子是,它们不尊重某些KVO选项,如
nsKeyValueObservingOptionPrevior
)如果您希望它们在KVO方面表现得像“正常”对象,您会感到失望。它们的存在主要是为了支持Cocoa绑定。虽然乍一看,绑定可能看起来只是KVO之上的语法糖,但您可以看到(通过覆盖绑定到对象的支持KVO的方法并在其中设置断点),实际上,在封面下发生的事情比简单的KVO观察要多得多


请增加他们解决(或至少记录)此类问题/行为的可能性。

如果您找到原因,请与他人分享;)我现在正在观察
KVO
的奇怪行为,这些类是由
核心数据
实体生成的。您是否尝试过使用
+(NSSet*)keypathsforvaluesafectingvalueforkey:(NSString*)来进行验证改为键
?默认的
+keypathsforvaluesafectingvalueforkey:
实现只是搜索
+keypathsforvaluesafecting
并返回其结果——覆盖它在这里没有任何区别。叹气。这当然可以解释为什么我无法根据我的
NSArrayController
属性的
selectionIndex
(或
selection
)来创建属性。。非常烦人-谢谢你的信息@ipmcc:您是否知道缺少对
nsKeyValueObservingOptionPrevior
(顺便说一句,*新选项和*旧选项)的支持是否有文档记录?因为有趣的是,Apple文档声明“此对象完全符合键值编码”@Mojo66,就像许多Cocoa绑定一样,似乎没有文档记录。但是相信我……;)