(Apologies for over-quoting here. And for the length of the response.)

On Feb 2, 2010, at 07:42, Jerry Krinock wrote:

> On 2010 Feb 01, at 03:53, Quincey Morris wrote:
> 
>> I'd point you to the the documentation:
> 
>   (This is the quote from "Cocoa Bindings Programming Topics" the 
> documentation I quoted in my original post.)
> 
>> I don't see how this can be clearer that bindings are bidirectional.
> 
> Yes.  It is clear.  And I had always thought that bindings were 
> bidirectional, based on this documentation.  Then, two weeks ago, I noticed 
> that -bind:::only implemented observer behavior in one direction.  

There's no "observer behavior" *in* NSObject's 'bind:...'. It merely sets up an 
observation -- it does the equivalent of calling 'addObserver:forKeyPath:...'. 
The distinction is key. See below.

> I then read *this* documentation:
> 
>> bind:toObject:withKeyPath:options:
>> 
>> "Establishes a binding between a ..."
> 
> "Establishes a binding!"  So, then, having forgotten the other documentation, 
> I thought like Matt, that bindings are unidirectional.  Until I tried it with 
> an NSButton.

The 'bind:...' *method* isn't a binding. It's a method. It *establishes* a 
binding, but it isn't a binding. Just like [NSArray array] is a method that 
creates an array, but the method isn't the array, nor is the array behavior in 
the method. See below.

> So now we have this paradox:
> 
> 1.  "Cocoa Bindings Programming Topics" says that bindings are bidirectional.
> 2.  bind:toObject:withKeyPath:options: documentation says it "establishes a 
> binding"
> 3.  bind:toObject:withKeyPath:options: implementation establishes something 
> which
>    is unidirectional.

On Feb 2, 2010, at 10:06, Keary Suska wrote:

> No paradox, as I see it, because #3 is not precisely true. There is nothing 
> in the docs that says it is unidirectional, except in the sense that there is 
> always an active and passive partner (perhaps what Quincey meant by 
> "asymmetrical").

I agree there's no paradox, but I'd express it differently. There's no paradox 
if a bidirectional thing contains two uni-directional pieces. Not unless you 
confuse the pieces with the thing.

All implementations of 'bind:...' "establish a binding [link]", which is 
bidirectional. NSObject's implementation of 'bind:...' "establishes something 
which is unidirectional" -- namely a KVO observation -- which provides half of 
the necessary binding behavior to subclasses that wish to make use of it. The 
other half (the other direction) is left for individual subclasses to implement.


Let me take another stab at teasing out the strands. Feel free to stop reading 
here if your eyes have already glazed over.

1. There are three (3) [III] agents involved in a binding.

-- Class A (typically some kind of view) defines+implements a binding 
[behavior] identified by an attribute "x". "Attribute" is not the best choice 
of terminology, but it's what the documentation uses. It's basically an 
arbitrary string with a meaning that's internal to A, though sometimes it 
happens to be a KVC property name too. The attribute may or may not be 
"exposed" to IB as a "binding name".

-- Class B (typically a data model object) defines+implements a KVC property 
"y".

-- Class C (typically some kind of controller) is responsible for hooking 
things up. If the binding is set up in IB, C's behavior is somewhere inside the 
nib-loading code. If the binding is established programmatically, C is an 
application-defined class.

2. An object c of class C establishes a binding [link] from attribute "x" of an 
object a of class A to property "y" of an object b of class, by sending this 
message:

        [a bind: @"x" toObject: b withKeyPath: @"y" options: ...];

Note that A, B and C are *not* necessarily distinct. Often A == C and a == c:

        [self bind: @"x" toObject: b withKeyPath: @"y" options: ...];

In terms of establishing a binding [link], that's the whole story. C does not 
care what the implementation of 'bind:...' is -- that's an implementation 
detail inside A. All C cares about is that sending this message causes the 
binding [link] to exist.

Certainly C knows that 'bind:...' must set up some machinery to make A's 
binding [behavior] work, but it's a mistake to think that this machinery *is* 
the binding [behavior]. That's where the discussion usually goes off the rails. 
The train wreck is made more likely because:

-- there's no proper terminology to distinguish a binding [link] from a binding 
[behavior]

-- NSObject's implementation of 'bind:...' happens to do something that's sort 
of useful in isolation, if class A doesn't actually define binding "x' but has 
a KVC property "x"

It'd be better for everyone, I think, if NSObject had no implementation of 
'bind:...' at all, or if its implementation was moved to a convenience method 
that didn't mention the word "binding".

3. Class A is responsible for providing the binding [behavior]. This consists 
of three parts:

-- An implementation of NSKeyValueBindingProtocol. Most significantly, an 
implementation of the 'bind:...' method.

-- Detection of changes in the bound-to property ("y" in class B, above), and 
synchronization of its "x" attribute to such changes.

-- Propagation of changes to its "x" attribute to the bound-to property.

It can do this any way it wants. Really. An outside agent (class C) can assume 
*nothing* about the implementation of an arbitrary binding in A, beyond 
conformance to the protocol. The implementation may or may not use KVO. The 
implementation may or may not use NSObject's 'bind:...'.

If you follow along with the documentation, part 3 is always custom code. Part 
2 is most naturally done with KVO, and set up in the 'bind:...' method. Class A 
might provide its own implementation of that method, or it might leverage the 
NSObject implementation.

4. The disputatious part of all this is whether it's valid or safe for class C 
to send a 'bind: @"x" ...' message to an A object when A does *not* actually 
provide a binding [behavior] for "x" (such as, when "x" is merely a KVC 
property of A).

My answer is that it's not in the API contract, so it's not a good idea. Other 
people seem determined to do it anyway.


_______________________________________________

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

Reply via email to