4

У меня есть КВО-способный класс (назовем его Observee), который affectedValue динамическое свойство пораженной affectingValue собственности. Зависимость между свойствами определяется путем применения метода +keyPathsForValuesAffectingAffectedValue.КВО: + keyPathsForValuesAffecting <Key> не работает с (подкласс) NSObjectController

Установка значения для affectingValueaffectedValue сообщает, что изменилось, как я ожидал, если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 

пример работает отлично и выходы, как следующее, когда Observee происходит NSObject:

keyPathsForValuesAffectingAffectedValue called 
setting value to affectingValue 
affected key path = affectedValue 

но когда Observee происходит NSObjectController:

keyPathsForValuesAffectingAffectedValue called 
setting value to affectingValue 

(обратите внимание, что «пострадавших key path = affectedValue "отсутствует.)

Кажется, что в обоих случаях вызывается keyPathsForValuesAffectingAffectedValue, но в последнем случае он не работает.

Кроме того, любые ключевые пути, включающие экземпляр (подкласса) 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: и друзья, но подведению каждого затрагивающей ключевого пути с (ругой) сеттерами страшно, и я хотел бы избежать этого.)

+0

Если вы обнаружите, почему, пожалуйста, поделитесь;) Я сейчас наблюдаю странное поведение для 'KVO' с классами, созданными из сущностей Core Data. – Colas

+0

Вы пытались использовать '+ (NSSet *) keyPathsForValuesAffectingValueForKey: (NSString *) key' вместо этого? – Colas

+0

Реализация по умолчанию '+ keyPathsForValuesAffectingValueForKey:' просто ищет '+ keyPathsForValuesAffecting ' и возвращает свой результат - переопределение здесь не имеет значения. – uasi

ответ

5

NSController и его подклассы полны КВО «Черная магия» и неожиданное поведение. (В другом примере они не учитывают некоторые варианты KVO, такие как NSKeyValueObservingOptionPrior). Вы будете разочарованы, если вы ожидаете, что они будут вести себя как «нормальные» объекты по отношению к KVO. Они существуют прежде всего для поддержки привязок какао. Хотя на первый взгляд привязки могут выглядеть как простой синтаксический сахар поверх KVO, вы можете видеть (переопределяя методы поддержки KVO привязанного объекта и устанавливая в них точки останова), что на самом деле происходит довольно немного под крышками чем простое наблюдение КВО.

Пожалуйста, file bugs with Apple, чтобы увеличить вероятность того, что они будут исправлять (или хотя бы документировать) эти проблемы/поведение.

+0

** SIGH. ** Это, безусловно, объясняет, почему я просто не могу создавать свойства в зависимости от 'selectionIndexes' (или' selection') моих свойств свойств 'NSArrayController'. Очень раздражает - спасибо за информацию! – Jay