Hey list, I'm having some issues with KVO and updating UI elements via bindings; I'd greatly appreciate some clarification on the KVO-compliant way to do what I'm attempting:
I have a preferences controller object (let's call it PrefCtrl) that's modeled after NSUserDefaultsController (for various reasons, though, it's a custom implementation.) As does NSUDC, it has a 'values' property, which mediates access to the preferences. The bindings in the UI use this 'values' proxy object to access the preferences. The role of the proxy object is simple: it forwards KVC methods (-valueForUndefinedKey: and setValue:forUndefinedKey:) to PrefCtrl, which either supplies or sets the appropriate value. Preferences can change at anytime and potentially from other processes. (I've got the correct locking mechanisms in place, and such.) When the preferences change from 'under the feet' of the app in question, I expect the UI elements of the app to update accordingly (via bindings). In order to announce that the UI elements need updating, I wrap the preferences-updating code with willChange/didChangeValueForKey: - (void)preferencesOnDiskDidChangeNotification: (NSNotification *)notification { // This code is part of PrefCtrl [self willChangeValueForKey: @"values"]; ... read the prefs from disk, and update our in-memory prefs dictionary to reflect the new prefs ... [self didChangeValueForKey: @"values"]; } Now consider when I have UI elements bound to the PrefCtrl - for example, a button's enabled property is bound to PrefCtrl's values.someFeature (when a value exists for the 'values.someFeature' key path, the button's enabled, otherwise disabled.) This all works fine - when preferences change, the enabled state of the button reflects the current value of 'values.someFeature'. The problem arises when I have 3+ elements in the binding key path. For example, if the button's enabled property is bound to PrefCtrl's values.someFeature.isEnabled. In this case, when the value of 'values.someFeature.isEnabled' changes (let's assume due to another process re-writing the preferences) is when hell breaks loose and I get this delightful message: Cannot remove an observer <NSKeyValueObservance 0x137d50> for the key path "someFeature.isEnabled" from <PrefCtrl_Proxy 0x135bd0>, most likely because the value for the key "someFeature" has changed without an appropriate KVO notification being sent. Check the KVO-compliance of the PrefCtrl_Proxy class. (Note that PrefCtrl_Proxy is the class name of my 'values' proxy.) My question: Of course, this error is correct - the value for the 'someFeature' key DID change. But why wasn't sending willChange/didChangeValueForKey: @"values" enough to notify the KVO system that values.someFeature was also going to change? It seems implied that when announcing that the root segment of the key path ('values') is changing, all children keys will also be changing. But based on this console output, I suppose not. When the preferences change, do I really need to send willChange/didChange for every key that's present in 'values'? (Which makes everything work, by the way, but definitely isn't as easy as simple announcing that PrefCtrl's 'values' will change. I should also mention that I've found keyPathsForValuesAffectingValueForKey:, but it's just as clumsy as sending willChange/didChange for every key in 'values'.) What's even more confusing is that everything works fine when I exclude the 'isEnabled' suffix of the key path. That is, sending willChange/didChangeValueForKey: @"values" is sufficient when the button's enabled property is bound to values.someFeature; my UI updates accordingly and I don't receive any output in the console. I've created an example project that exhibits my problem, it's available here: http://www.docdave.com/kvo_project.zip I've been reading through the KVO documentation but I can't seem to find anything relevant to this issue (I'm not sure what I would even call this problem). Perhaps I'm blind - if you would be so kind to point me in the right direction :) Thanks a lot for any help! David _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com