(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 ([email protected])
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 [email protected]