Re: bind:toObject:withKeyPath:options: Unidirectional or Bidirectional?
Re: bind:toObject:withKeyPath:options: Unidirectional or Bidirectional?
- Subject: Re: bind:toObject:withKeyPath:options: Unidirectional or Bidirectional?
- From: Keary Suska <email@hidden>
- Date: Tue, 2 Feb 2010 16:51:28 -0700
On Feb 2, 2010, at 1:20 PM, Quincey Morris wrote:
> 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: ...];
This is not usually the case. Object c will usually emit:
[a bind: @"x" toObject: c withKeyPath: @"z" options: ...];
Where "z" is a property of c or a key path "z.y" as controllers typically "control" one model (b). If you write the controller you could certainly bind directly as you show, but then you have to unbind/rebind any time your model object changes (to a different object), or you have to wait until the model object exists before binding. Not a very extensible design.
> 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"
I don't believe this is true--it is simply the default behavior of NSObject (se also below) when "A" has KVC property "x". The one bind call is sufficient for the entire binding behavior to function, as long as every key along the bound key path is KVO compliant. Nothing additional is required. There is documentation about cleaning up bindings, but I think even that is done automatically for conforming properties.
> 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.
Yes, except for the "z"/"z.y" clarifications above.
> -- 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:...'.
Well, C *can* assume that if it emits a KVO notice of a bound property that it has fulfilled its part of the bargain. This is a documented necessity--all bound objects along the key path must be KVO compliant. Whether or not "A" does anything about it is another matter. "A" could be broken.
> 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.
No, NSObject has a default implementation for part 3. You don't need to code anything. You *could*, but you don't have to as long as your follow KVO rules. I don't think this is an accident--it is by design. In the same way that an accessor is not necessarily an ivar, a binding name is not necessarily a named property in any official sense, but that doesn't define its behavior, it simply reflects its interface.
> 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.
I suppose anything is ultimately disputable, but I would argue that it is documented that NSObject implements the binding protocol and I take that to mean it fulfills the API contract. Practice also shows this to be true.
Keary Suska
Esoteritech, Inc.
"Demystifying technology for your home or business"
_______________________________________________
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