KVO In Objective-J

32 views
Skip to first unread message

Keary Suska

unread,
Oct 27, 2016, 2:01:20 PM10/27/16
to objec...@googlegroups.com
I occasionally run into frustrating debug issues as I forget that Objective-J will only set one observer per object/keypath (since Objective-C doesn’t work this way). It also appears that which addObserver… call will be “set” is somewhat undefined (or defined by obscure criteria). Are there any plans to expand this to allow multiple observers (same observer for same keypath)? Looking at the code it looks nontrivial but not insurmountable.

TIA,

Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"

daboe01

unread,
Oct 28, 2016, 4:58:50 AM10/28/16
to Cappuccino & Objective-J, cappu...@esoteritech.com
are multiple observers for any given keypath possible in cocoa?
if so, please file a bug on github.  preferably with a reduction.

Martin Carlberg

unread,
Oct 28, 2016, 5:19:21 AM10/28/16
to objec...@googlegroups.com
Hi!

Yes, the implementation for this is nontrivial. :-) It will help us a lot if you can create a unit test case that will show you problem. We have a lot of unit test cases for Key Value Observing in CPKeyValueObservingTest.j. Maybe in other files too. They will help you setup your problem with a nice looking unit test.

You can even create a pull request on Github with just the test case and we can continue the discussion there.


Thanks,

- Martin


--
You received this message because you are subscribed to the Google Groups "Cappuccino & Objective-J" group.
To unsubscribe from this group and stop receiving emails from it, send an email to objectivej+...@googlegroups.com.
To post to this group, send email to objec...@googlegroups.com.
Visit this group at https://groups.google.com/group/objectivej.
For more options, visit https://groups.google.com/d/optout.

Alexander Ljungberg

unread,
Oct 28, 2016, 8:54:42 AM10/28/16
to objec...@googlegroups.com

Hi,

Sorry for dropping into a conversation I might not fully follow.

Of course you can add multiple observers per object and key path. I assume you’re talking about objects A and B both observing changes to C.somePath. Take a look at testSettingObservingNewPlusAnotherObserverWithNoNew in CPKeyValueObservingTest.j for a simple example.

Or do you mean you want to add the same observer twice? Like having A observe C.somePath in duplicate? There really should be no reason to do that. You’d just get a duplicate notification sent to A.




Alexander

Keary Suska

unread,
Oct 28, 2016, 11:12:29 AM10/28/16
to objec...@googlegroups.com

> On Oct 28, 2016, at 2:58 AM, daboe01 <dab...@googlemail.com> wrote:
>
> are multiple observers for any given keypath possible in cocoa?
> if so, please file a bug on github. preferably with a reduction.

Yes, though some coalescing may have popped up around 10.9 or thereabouts as I recall some buzz over a greater importance of using good contextInfo values. I was often a source of strange bugs when developers would have unintentional multiple observations.

> Am Donnerstag, 27. Oktober 2016 20:01:20 UTC+2 schrieb Keary Suska:
> I occasionally run into frustrating debug issues as I forget that Objective-J will only set one observer per object/keypath (since Objective-C doesn’t work this way). It also appears that which addObserver… call will be “set” is somewhat undefined (or defined by obscure criteria). Are there any plans to expand this to allow multiple observers (same observer for same keypath)? Looking at the code it looks nontrivial but not insurmountable.

Keary Suska

unread,
Oct 28, 2016, 11:45:17 AM10/28/16
to objec...@googlegroups.com

> On Oct 28, 2016, at 6:54 AM, Alexander Ljungberg <stil...@gmail.com> wrote:
>
> Hi,
>
> Sorry for dropping into a conversation I might not fully follow.
>
> Of course you can add multiple observers per object and key path. I assume you’re talking about objects A and B both observing changes to C.somePath. Take a look at testSettingObservingNewPlusAnotherObserverWithNoNew in CPKeyValueObservingTest.j for a simple example.
>
> Or do you mean you want to add the same observer twice? Like having A observe C.somePath in duplicate? There really should be no reason to do that. You’d just get a duplicate notification sent to A.

It would be object A observing the same keypath twice. In my use case, the object’s superclass observes paths for its purposes, but occasionally my subclasses need to observe one or more same keypaths for different purposes. The issue is that I would always have to check whether the superclass is observing certain keypaths, which is an OOP violation, or worse, if I am subclassing an CPController, checking all of the bindings. And in this latter case, adding bindings at some later point in development could introduce hard-to-diagnose bugs.

This is further a problem because which observation “sticks”, or more precisely which contentInfo value is stored. Because, consistent with Cocoa, I rely non the contextInfo value to distinguish the purpose of the observation, and I don’t get a predictable contextInfo value. I.e., I may expect the the latter addObserver calls would replace the former, or be ignored, but this apparently is not always the case. This complicates the CPController case above.

Not to mention that the current behavior is not “Cocoa-like” and that violates one of Cappuccino’s founding principles ;-)

The easiest stop-gap measure, IMHO, would be to raise a runtime exception for any attempt to add an observance with a duplicate observer and keypath, so at least the developer is alerted to a potential problem.

I will add this to mu bug fix list.

Alexander Ljungberg

unread,
Oct 28, 2016, 12:10:13 PM10/28/16
to objec...@googlegroups.com

Hi,

Normally if your subclass listens for observations too, it would call the super class observation method as needed.

You can also just use a delegate. Create a special observer instance whose only job is to receive the notifications.

I think your use case sounds a little too abstract for me. Maybe if you had a more specific example it would be easier to reason about.

That said if you’re right that Cocoa allows duplicate observers, that might warrant a change to Cappuccino. But we don’t necessarily copy Cocoa bug for bug – if it looks unintentional or we can’t understand what’s going we don’t copy that feature. We’re not a cargo cult. :)




Alexander

Keary Suska

unread,
Oct 30, 2016, 1:36:04 PM10/30/16
to objec...@googlegroups.com

> On Oct 28, 2016, at 10:10 AM, Alexander Ljungberg <stil...@gmail.com> wrote:
>
> Hi,
>
> Normally if your subclass listens for observations too, it would call the super class observation method as needed.
>
> You can also just use a delegate. Create a special observer instance whose only job is to receive the notifications.

Certainly, my workaround is to avoid duplicate observation and pass the method upstream.

> I think your use case sounds a little too abstract for me. Maybe if you had a more specific example it would be easier to reason about.

FWIW, I will give a specific use case that explains my situation, using a more generally understood milieu than my specific application:

Say we have a UI where we allow a user to edit their “profile” which includes various personal information. We need to watch all of the fields for changes so we can, among other things. prompt the user to save changes if they close the window or navigate away without executing an explicit save. Since this application does quite a bit of this kind of UI for different kinds of data sets, in typical OOP style this watch-and-check-save behavior is abstracted to a base class, but we have a specific subclass to manage the specifics for the “profile” data set. Specifically for this “profile” data set, there is a popup button, “preferred method of contact”, with the options: “Phone Call”, “Email Message”, and “Snail Mail”. The profile class has to watch the methodOfContactValue for a change, and present a different data entry UI. So the subclass wants to observe changes to the data value, but the super class also has to watch changes so it can determine an “edited” state for the UI.

In the Cocoa world, each implementation would use a different contextInfo value, and so (at least) receive multiple notifications, each observeValue implementation checking the contextInfo to see if the change concerns it and then acting upon it as necessary.

> That said if you’re right that Cocoa allows duplicate observers, that might warrant a change to Cappuccino. But we don’t necessarily copy Cocoa bug for bug – if it looks unintentional or we can’t understand what’s going we don’t copy that feature. We’re not a cargo cult. :)

I reality the bugs are due to developers not using the API correctly, so that is less an issue. Apple’s documentation o KVO and the use of contextInfo addresses my use case:

"The context pointer in the addObserver:forKeyPath:options:context: message contains arbitrary data that will be passed back to the observer in the corresponding change notifications. You may specify NULL and rely entirely on the key path string to determine the origin of a change notification, but this approach may cause problems for an object whose superclass is also observing the same key path for different reasons.

A safer and more extensible approach is to use the context to ensure notifications you receive are destined for your observer and not a superclass.”

I can’t think of a use case (and can think of undesired side-effects) for sending one notification for every addObserver call, but at least one call per unique observer, key path, and contextInfo would be best. The former, however, would likely be easier to implement, especially taking into account null or undefined contextInfo values.

For now, I will just put raising an exception on my list of fixes. I may look at it later to see if I can make sense of how KVO is implemented, and see what the best approach will be.
Reply all
Reply to author
Forward
0 new messages