• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: KVO & Bindings: Proxy object & change notifications
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: KVO & Bindings: Proxy object & change notifications


  • Subject: Re: KVO & Bindings: Proxy object & change notifications
  • From: Ken Thomases <email@hidden>
  • Date: Wed, 11 Mar 2009 00:52:01 -0500

On Mar 10, 2009, at 4:14 AM, Dave Keck wrote:

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.

[...]

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.

Are you sure that PrefCtrl is returning the same proxy each time?

Also, at the time that you invoke -willChangeValueForKey: have you already changed your internal state such that invoking [theProxy valueForKey:@"someFeature"] returns the "after" value? It should still return the "before" value at that point. It must not return the "after" value until after the -willChangeValueForKey: call completes.


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 is enough. However, KVO has to unwind the set of observations on individual objects it did along the key path. In order to do that, it has to invoke -valueForKey: on the first object to get the second, on the second to get the third, etc. If any of those doesn't give back the same object it did when the original observation was established, then it can't unwind what it did.


That's what it's complaining about. It's saying that [theProxy valueForKey:@"someFeature"] isn't the same object it was when the observation was established, so KVO can't unhook itself from the object it had earlier hooked into. Note that it's attempting this unwinding during -willChangeValueForKey:. Of course, that object won't be the same _after_ -willChangeValueForKey: -- you are, after all, changing it -- but it needs it to be the same _at_ - willChangeValueForKey: for KVO's housekeeping to work.

Also, since KVO was watching the "someFeature" property of the proxy, and that property is different than it was, but KVO never noticed that it changed, it's reporting that the property changed in a non-KVO- compliant fashion. Since you are using a proxy to front for your PrefCtrl, are you also making sure that all changes of PrefCtrl's properties cause change notifications for the proxy's virtual properties? That is, are you forwarding all -will/didChange... invocations on your PrefCtrl object to your proxy, at least for keys other than "values"?

You may be able to eliminate the proxy altogether, by the way. Have you tried having the "values" property of the PrefCtrl object just return "self" -- the PrefCtrl object itself? That would avoid the need to forward things in either direction, but still give you the ability to will/didChange... the "values" property to provoke a wholesale updating of all observers of any properties. At least, I think that should work.

Regards,
Ken

_______________________________________________

Cocoa-dev mailing list (email@hidden)

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:
This email sent to email@hidden


  • Follow-Ups:
    • Re: KVO & Bindings: Proxy object & change notifications
      • From: Dave Keck <email@hidden>
References: 
 >KVO & Bindings: Proxy object & change notifications (From: Dave Keck <email@hidden>)

  • Prev by Date: Re: Background Process?
  • Next by Date: Re: Background Process?
  • Previous by thread: KVO & Bindings: Proxy object & change notifications
  • Next by thread: Re: KVO & Bindings: Proxy object & change notifications
  • Index(es):
    • Date
    • Thread