Why aren't my bindings firing?

  • Okay, in a project I'm working on, I made the mistake of trying to do
    something simple with the weird deep magic known as Cocoa Bindings.
    I've got two classes - let's call them "Foo" and "Bar". Foo's
    implementation has this in it:

    - (void)setDisplayName:(NSString *)name {
        [self willChangeValueForKey:@"displayName"];

        NSLog(@"setting display name to %@", name);

        if(name != ivar_displayName) {
            [ivar_displayName release];
            ivar_displayName = [name copy];
        }

        [self didChangeValueForKey:@"displayName"];
    }

    whereas Bar's implementation has this:

    - (void)setTitle:(NSString *)title {
        [self willChangeValueForKey:@"title"];

        NSLog(@"setting title to %@", title);

        if(title != ivar_title) {
            [ivar_title release];
            ivar_title = [title copy];
        }

        [self didChangeValueForKey:@"title"];
    }

    Foo and Bar are both instantiated in Interface Builder, and Foo has an
    outlet to Bar. There's also an NSObjectController that's got its
    content outlet pointed at Foo. Foo has an outlet called
    "ivar_controller" that points to that NSObjectController. Foo's also
    got a method that returns its Bar outlet:

    - (Bar *)bar {
        return ivar_bar;
    }

    and in Foo's windowControllerDidLoadNib: method (it's an NSDocument
    subclass) I've got this:

    [[self bar] bind:@"title" toObject:ivar_controller
    withKeyPath:@"selection.displayName" options:nil];

    Now here's the thing: if I call setDisplayName: on Foo, it calls Bar's
    setTitle: method, exactly as it should. However, if I call setTitle:
    on Bar, it does *not* end up calling Foo's setDisplayName: method,
    although it seems like it should. I can change the
    bind:toObject:withKeyPath:options: invocation above so that it binds
    Bar directly to Foo without going through the object controller, or I
    can try going the other way and binding the Foo to the Bar - always I
    get the same result.

    I'm sure I'm doing something stupid and/or missing something really
    simple, but what?

    Thanks,
    Charles
  • 6/27/08 1:37 PM, also sprach <cocoadev...>:

    > I've got two classes - let's call them "Foo" and "Bar". Foo's
    > implementation has this in it:
    >
    > - (void)setDisplayName:(NSString *)name {
    > [self willChangeValueForKey:@"displayName"];
    >
    > NSLog(@"setting display name to %@", name);
    >
    > if(name != ivar_displayName) {
    > [ivar_displayName release];
    > ivar_displayName = [name copy];
    > }
    >
    > [self didChangeValueForKey:@"displayName"];
    > }
    >
    > whereas Bar's implementation has this:
    >
    > - (void)setTitle:(NSString *)title {
    > [self willChangeValueForKey:@"title"];
    >
    > NSLog(@"setting title to %@", title);
    >
    > if(title != ivar_title) {
    > [ivar_title release];
    > ivar_title = [title copy];
    > }
    >
    > [self didChangeValueForKey:@"title"];
    > }

    If you aren't overriding +automaticallyNotifiesObserversForKey: to return
    NO, you should not be calling  willChangeValueForKey/didChangeValueForKey in
    your setters. They are KVC-compliant as shown. Fix that, then see if the
    problem goes away.

    Best,

    Keary Suska
    Esoteritech, Inc.
    "Demystifying technology for your home or business"
  • On Jun 27, 2008, at 5:17 PM, Keary Suska wrote:

    > If you aren't overriding +automaticallyNotifiesObserversForKey: to
    > return
    > NO, you should not be calling  willChangeValueForKey/
    > didChangeValueForKey in
    > your setters. They are KVC-compliant as shown. Fix that, then see if
    > the
    > problem goes away.

    Actually, that's what I tried first - I added the willChange/didChange
    methods to see if that would fix the problem. It didn't - it behaves
    the same way with or without those methods. I've also tried overriding
    +automaticallyNotifiesObserversForKey: to return NO, but it turns out
    that that method never even ends up getting called (I put a log in it
    to check).

    Thanks,
    Charles
  • On Jun 27, 2008, at 2:37 PM, Charles Srstka wrote:

    > and in Foo's windowControllerDidLoadNib: method (it's an NSDocument
    > subclass) I've got this:
    >
    > [[self bar] bind:@"title" toObject:ivar_controller
    > withKeyPath:@"selection.displayName" options:nil];
    >
    > Now here's the thing: if I call setDisplayName: on Foo, it calls
    > Bar's setTitle: method, exactly as it should. However, if I call
    > setTitle: on Bar, it does *not* end up calling Foo's
    > setDisplayName: method, although it seems like it should. I can
    > change the bind:toObject:withKeyPath:options: invocation above so
    > that it binds Bar directly to Foo without going through the object
    > controller, or I can try going the other way and binding the Foo to
    > the Bar - always I get the same result.
    >
    > I'm sure I'm doing something stupid and/or missing something really
    > simple, but what?

    A binding is not just an automated two-way connection between KVC/KVO-
    conforming properties.

    In particular, the binding name you pass to
    bind:toObject:withKeyPath:options: is not in the same "namespace" as
    properties.  Binding names are something else.  Furthermore,
    implementing bindings is more than just creating KVC/KVO-conforming
    properties.  A binding is a specific feature of a class which
    requires a specific implementation.  See "How Do Bindings Work?" in
    the Cocoa Bindings Programming Topics to see code listings which
    illustrate the work that must be done to make a class support a binding.

    http://developer.apple.com/documentation/Cocoa/Conceptual/
    CocoaBindings/Concepts/HowDoBindingsWork.html

    You might be tempted to create a two-way connection between
    properties by using KVO.  It might work, but I suspect you'll get
    infinite loops.

    As a matter of design, you shouldn't hook two properties up in this
    way to try to keep them always equal.  If they're always equal, why
    store the data in two places?  The state of the application (or
    document or whatever) should be stored (once) in the model.  The
    controller is responsible for reading the state of the model and
    configuring the view to reflect that.  (Both parts of that may be
    automated using KVO, but note that both the controller and the view
    will have to implement specific response to the KVO notifications.
    The view's specific response is part of implementing a binding.)  In
    response to user manipulation, a view may inform the controller of
    some action or new value.  (Again, this part of the view's behavior
    may be implemented for a binding, in which case it might inform the
    controller using KVC.)  The controller in turn translates that action
    or value change into instructions to the model to modify itself.
    (This is often custom, direct invocation of the model's methods, but
    may also be done via KVC.)

    I responded to a similar question the other day, and that thread may
    also be helpful: <http://lists.apple.com/archives/cocoa-dev/2008/Jun/
    msg01484.html
    >.

    Cheers,
    Ken
  • On Jun 27, 2008, at 8:06 PM, Ken Thomases wrote:

    > A binding is not just an automated two-way connection between KVC/
    > KVO-conforming properties.
    >
    > In particular, the binding name you pass to
    > bind:toObject:withKeyPath:options: is not in the same "namespace" as
    > properties.  Binding names are something else. Furthermore,
    > implementing bindings is more than just creating KVC/KVO-conforming
    > properties.  A binding is a specific feature of a class which
    > requires a specific implementation.  See "How Do Bindings Work?" in
    > the Cocoa Bindings Programming Topics to see code listings which
    > illustrate the work that must be done to make a class support a
    > binding.
    >
    > http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Con
    cepts/HowDoBindingsWork.html

    >
    >
    > You might be tempted to create a two-way connection between
    > properties by using KVO.  It might work, but I suspect you'll get
    > infinite loops.
    >
    > As a matter of design, you shouldn't hook two properties up in this
    > way to try to keep them always equal.  If they're always equal, why
    > store the data in two places? The state of the application (or
    > document or whatever) should be stored (once) in the model.  The
    > controller is responsible for reading the state of the model and
    > configuring the view to reflect that.  (Both parts of that may be
    > automated using KVO, but note that both the controller and the view
    > will have to implement specific response to the KVO notifications.
    > The view's specific response is part of implementing a binding.)  In
    > response to user manipulation, a view may inform the controller of
    > some action or new value.  (Again, this part of the view's behavior
    > may be implemented for a binding, in which case it might inform the
    > controller using KVC.)  The controller in turn translates that
    > action or value change into instructions to the model to modify
    > itself.  (This is often custom, direct invocation of the model's
    > methods, but may also be done via KVC.)

    Well I'll admit that I'm relatively new to bindings, because most of
    the work I've done with Cocoa has been with old projects that
    originated prior to their introduction, so I haven't really been too
    much into the bindings concept, which is why I'm trying to get myself
    up to speed now, and pretty much teach myself how they work. With that
    said, aren't bindings *always* creating a two-way connection between
    properties? For example, say you have a generalized view like an
    NSTextField. It's got a property called "stringValue" which is set via
    the -stringValue and -setStringValue: methods. Sure, as a view, it's
    rendering an object from my model on the screen, but at the same time
    it's gotta store its data somewhere, because otherwise its drawRect:
    method won't know what it should draw, and of course NSTextField can't
    know about the objects in your model, because if it did, then it
    wouldn't work with any other models and would lose its generalization,
    working only with the specific model that existed in your application.
    Now normally, an app would set the NSTextField's "stringValue"
    property via the accessor methods, but now Bindings present us with a
    new way to bind a property in the model with the "stringValue"
    property in the NSTextField.

    Or that's what I thought it was, anyway. If Bindings don't do that,
    then I'm a little confused as to what they actually *do*.

    In my case, what I have is a document object and a bunch of view
    objects of a certain class. The view object's class wraps some
    portable code that I didn't write, and basically provide some glue
    between a portable C++ object and the Cocoa Obj-C system, with some
    drawing methods on top to display the object. The view has a "title"
    property set by the portable code (which my glue code bridges to the
    setter method of the view object when the portable code wants to
    change it). Usually the title is an independent property of the view
    class, but for this one particular instance of that class I want to
    bind it to my document's display name so that it will be the window's
    title, but only for that particular instance, not for every instance
    of the class. Now I could do that easily enough via notifications, and
    that's what I would have done in 2004, when I still had to support
    Jaguar, but part of the reason I'm trying to do this is because I'm
    trying to teach myself about the "new" stuff (I realize the concept of
    bindings is actually a few years old by now) so that I can get a grasp
    of what it is, and how to use it. In actuality, there would be a few
    more properties I'd want to bind later on, but first I need to know
    exactly what is the difference between binding the title of a view
    object to a variable in the model or controller, or doing the same
    thing with the many bindable properties exposed by view objects in
    Interface Builder, such as "Font" in an NSTextField, "Tool Tip" in a
    button, or "Enabled" or "Hidden" in pretty much anything. There's
    clearly some part of the concept I'm missing - but what is it?

    Apologies for my long-winded post,
    Charles
  • On Jun 27, 2008, at 11:08 PM, Charles Srstka wrote:

    > With that said, aren't bindings *always* creating a two-way
    > connection between properties?

    Not exactly, no.  A binding is a different thing than a property.

    (By the way, did you read the "How Do Bindings Work?" chapter I linked
    to, or the earlier thread?)

    > For example, say you have a generalized view like an NSTextField.
    > It's got a property called "stringValue" which is set via the -
    > stringValue and -setStringValue: methods. Sure, as a view, it's
    > rendering an object from my model on the screen, but at the same
    > time it's gotta store its data somewhere, because otherwise its
    > drawRect: method won't know what it should draw, and of course
    > NSTextField can't know about the objects in your model, because if
    > it did, then it wouldn't work with any other models and would lose
    > its generalization, working only with the specific model that
    > existed in your application. Now normally, an app would set the
    > NSTextField's "stringValue" property via the accessor methods, but
    > now Bindings present us with a new way to bind a property in the
    > model with the "stringValue" property in the NSTextField.

    Actually, NSTextField does not have a binding named "stringValue",
    even though it does have a property with that name.  Conversely, it
    has a binding called "value", although it doesn't have a property by
    that name.  See the NSTextField bindings reference: <http://developer.apple.com/documentation/Cocoa/Reference/CocoaBindingsRef/B
    indingsText/NSTextField.html
    >.

    What "has a binding called 'value'" means is described in that how-it-
    works document.  The NSTextField does use KVO to register itself as an
    observer of the bound-to object and key path.  However, what it does
    with the notifications it receives because of that observation is
    implementation dependent.  In this case, if you think of it as though
    it's keeping its stringValue property synced with the property named
    by the key path you won't go too far wrong, but that's because that's
    what NSTextField chooses to do with it.  For your own view class, you
    don't get that behavior automatically just by calling
    bind:toObject:withKeyPath:options:.  If that's the behavior you want,
    you have to code it into your view class.  In your original post, you
    merely called bind:toObject:withKeyPath:options: and expected the two
    properties to be synchronized.

    By the way, it's far from obvious that binding an NSTextField's
    "value" binding corresponds to syncing its "stringValue" property with
    some other object's property.  Note that NSTextField also has
    doubleValue, intValue, and floatValue properties, not to mention tons
    of other more-obviously-unrelated properties.  Also note that, when
    you set up the value binding of an NSTextField (either in IB or in
    code), there's no opportunity to specify which of these properties is
    to be kept in sync.  That should tell you that there must be some
    other "smarts" (i.e. code) involved.  KVC and KVO are not sufficient,
    although they are involved.

    > Or that's what I thought it was, anyway. If Bindings don't do that,
    > then I'm a little confused as to what they actually *do*.

    They are for keeping views and models in sync without a lot of glue
    code.

    Now, of course views have internal state (whether it's exposed as
    properties or not).  And models also have state (usually accessible as
    properties).  So, it's not surprising that your conception of bindings
    is that they just keep those two pieces of state in sync.  However,
    note that a view's state may not have a direct mapping to a model's
    state and vice versa.  Bindings are more general than just "connect
    this model property to that view property, and that's that".

    Bindings allow you to keep a _conceptual_ attribute of the view class
    in sync with the model.  The binding name names the conceptual
    attribute.  For example, NSTextField offers to allow you to bind its
    "value" -- which is a conceptual attribute which doesn't directly
    correspond to any property -- to an object and key path.  How it
    maintains that "value" attribute in response to changes in the named
    property is custom to NSTextField.  It doesn't just magically fall out
    of KVC and KVO.

    If you want your class to support a binding, you have to 1) identify
    the conceptual attribute available for binding, 2) pick a name for
    that conceptual attribute (which is in a different namespace than the
    class's properties, and so may or may not match one), and 3) implement
    the custom logic for how to map from that conceptual attribute to both
    the class's internal state and the bound property of the other object.

    Is that any clearer?

    Regards,
    Ken
  • On Jun 28, 2008, at 1:00 AM, Ken Thomases wrote:

    > Actually, NSTextField does not have a binding named "stringValue",
    > even though it does have a property with that name.  Conversely, it
    > has a binding called "value", although it doesn't have a property by
    > that name.  See the NSTextField bindings reference: <http://developer.apple.com/documentation/Cocoa/Reference/CocoaBindingsRef/B
    indingsText/NSTextField.html
    > >.
    >
    > What "has a binding called 'value'" means is described in that how-
    > it-works document.  The NSTextField does use KVO to register itself
    > as an observer of the bound-to object and key path.  However, what
    > it does with the notifications it receives because of that
    > observation is implementation dependent.  In this case, if you think
    > of it as though it's keeping its stringValue property synced with
    > the property named by the key path you won't go too far wrong, but
    > that's because that's what NSTextField chooses to do with it.  For
    > your own view class, you don't get that behavior automatically just
    > by calling bind:toObject:withKeyPath:options:.  If that's the
    > behavior you want, you have to code it into your view class.  In
    > your original post, you merely called
    > bind:toObject:withKeyPath:options: and expected the two properties
    > to be synchronized.
    >
    > By the way, it's far from obvious that binding an NSTextField's
    > "value" binding corresponds to syncing its "stringValue" property
    > with some other object's property.  Note that NSTextField also has
    > doubleValue, intValue, and floatValue properties, not to mention
    > tons of other more-obviously-unrelated properties.  Also note that,
    > when you set up the value binding of an NSTextField (either in IB or
    > in code), there's no opportunity to specify which of these
    > properties is to be kept in sync.  That should tell you that there
    > must be some other "smarts" (i.e. code) involved.  KVC and KVO are
    > not sufficient, although they are involved.
    >
    >
    >> Or that's what I thought it was, anyway. If Bindings don't do that,
    >> then I'm a little confused as to what they actually *do*.
    >
    > They are for keeping views and models in sync without a lot of glue
    > code.
    >
    > Now, of course views have internal state (whether it's exposed as
    > properties or not).  And models also have state (usually accessible
    > as properties).  So, it's not surprising that your conception of
    > bindings is that they just keep those two pieces of state in sync.
    > However, note that a view's state may not have a direct mapping to a
    > model's state and vice versa.  Bindings are more general than just
    > "connect this model property to that view property, and that's that".
    >
    > Bindings allow you to keep a _conceptual_ attribute of the view
    > class in sync with the model.  The binding name names the conceptual
    > attribute.  For example, NSTextField offers to allow you to bind its
    > "value" -- which is a conceptual attribute which doesn't directly
    > correspond to any property -- to an object and key path.  How it
    > maintains that "value" attribute in response to changes in the named
    > property is custom to NSTextField.  It doesn't just magically fall
    > out of KVC and KVO.
    >
    > If you want your class to support a binding, you have to 1) identify
    > the conceptual attribute available for binding, 2) pick a name for
    > that conceptual attribute (which is in a different namespace than
    > the class's properties, and so may or may not match one), and 3)
    > implement the custom logic for how to map from that conceptual
    > attribute to both the class's internal state and the bound property
    > of the other object.
    >
    > Is that any clearer?

    Hmm, you appear to be right. I'd forgotten that the text field's
    actual binding was named "value". And no instance variable named
    "value" appears to be implemented in NSTextField or any of its
    superviews. Huh.

    I guess the only question I still have then is: why did my example
    worke one-way in the first place? If the bindings are in a different
    namespace, shouldn't it have failed for lack of an exposed binding
    named "title" in the Bar object? Or is there a *little* magic going on
    here, just not going all the way?

    I'd still prefer it if the system automatically provided support for
    binding two properties to each other, for the cases where a property
    *would* map one-to-one with the binding you wanted in the view (which
    seems like it would have to happen quite frequently, especially for
    the simpler bindings like font, color, enabled, etc.), while allowing
    you to override that with custom code if needed. But at least now I'm
    starting to feel like I'm beginning to understand how this thing
    works, which is good. It's so frustrating when you're trying to work
    with something that seems to be incomprehensible black magic.

    Thanks,
    Charles
  • On Jun 28, 2008, at 1:30 AM, Charles Srstka wrote:

    > I guess the only question I still have then is: why did my example
    > worke one-way in the first place? If the bindings are in a different
    > namespace, shouldn't it have failed for lack of an exposed binding
    > named "title" in the Bar object? Or is there a *little* magic going
    > on here, just not going all the way?

    That depends on how the bar class from your OP (or one of its
    superclasses) implemented bind:toObject:withKeyPath:options:.  That
    code may not have checked the passed-in binding name, and may have
    unconditionally added itself as an observer of ivar_controller for the
    key path "selection.displayName".  That would have guaranteed that bar
    would receive observeValueForKeyPath:ofObject:change:context: messages
    whenever foo's displayName property was changed in a KVO-conforming
    manner.  (For example, if, in listing 2 of the how-it-works document,
    the check of the binding name against "angle" were omitted.)

    Then, what happens next is up to bar's implementation of
    observeValueForKeyPath:ofObject:change:context:.  If it blindly did
    [self setTitle:[object valueForKeyPath:keyPath]], then that would
    explain it.  (For example, if, in listing 4, the test of context were
    omitted.)

    Regards,
    ken
  • On Jun 28, 2008, at 1:57 AM, Ken Thomases wrote:

    > That depends on how the bar class from your OP (or one of its
    > superclasses) implemented bind:toObject:withKeyPath:options:.  That
    > code may not have checked the passed-in binding name, and may have
    > unconditionally added itself as an observer of ivar_controller for
    > the key path "selection.displayName".  That would have guaranteed
    > that bar would receive
    > observeValueForKeyPath:ofObject:change:context: messages whenever
    > foo's displayName property was changed in a KVO-conforming manner.
    > (For example, if, in listing 2 of the how-it-works document, the
    > check of the binding name against "angle" were omitted.)
    >
    > Then, what happens next is up to bar's implementation of
    > observeValueForKeyPath:ofObject:change:context:.  If it blindly did
    > [self setTitle:[object valueForKeyPath:keyPath]], then that would
    > explain it.  (For example, if, in listing 4, the test of context
    > were omitted.)

    The superclass would be NSView, which doesn't declare
    bind:toObject:withKeyPath:options: in its header file, nor does
    NSResponder, so it's likely NSObject's implementation, whatever it
    does. Interestingly, NSObject's header file doesn't declare this as a
    method either, although NSKeyValueBinding.h declares it as a category
    on NSObject, which is apparently why the compiler doesn't complain.

    Also interestingly, the only reference to the
    bind:toObject:withKeyPath:options: method that comes up in an API
    search of the documentation is from the NSKeyValueBindingCreation
    protocol, which states this:

    "Establishes a binding between a given property of the receiver and
    the property of a given object specified by a given key path."

    Since this doesn't seem to be actually the case, someone ought to file
    a report on the documentation about this.

    Oh well, thanks for your patience with my questions.

    Charles
  • On Jun 28, 2008, at 3:10 AM, Charles Srstka wrote:

    > On Jun 28, 2008, at 1:57 AM, Ken Thomases wrote:
    >
    >> That depends on how the bar class from your OP (or one of its
    >> superclasses) implemented bind:toObject:withKeyPath:options:.  That
    >> code may not have checked the passed-in binding name, and may have
    >> unconditionally added itself as an observer of ivar_controller for
    >> the key path "selection.displayName".  That would have guaranteed
    >> that bar would receive
    >> observeValueForKeyPath:ofObject:change:context: messages whenever
    >> foo's displayName property was changed in a KVO-conforming manner.
    >> (For example, if, in listing 2 of the how-it-works document, the
    >> check of the binding name against "angle" were omitted.)
    >>
    >> Then, what happens next is up to bar's implementation of
    >> observeValueForKeyPath:ofObject:change:context:.  If it blindly did
    >> [self setTitle:[object valueForKeyPath:keyPath]], then that would
    >> explain it.  (For example, if, in listing 4, the test of context
    >> were omitted.)
    >
    > The superclass would be NSView, which doesn't declare
    > bind:toObject:withKeyPath:options: in its header file, nor does
    > NSResponder, so it's likely NSObject's implementation, whatever it
    > does. Interestingly, NSObject's header file doesn't declare this as
    > a method either, although NSKeyValueBinding.h declares it as a
    > category on NSObject, which is apparently why the compiler doesn't
    > complain.

    Yeah, it surprises me, too, that NSObject has an implementation of
    bind:toObject:withKeyPath:options:.  I had thought that it was just
    part of an informal protocol -- that is, that it was declared in a
    category on NSObject, but never implemented except by specific classes
    which adopted that protocol.  However, I did a symbol dump of the
    AppKit framework and I see that there is, in fact, an implementation.
    I have no idea what it could be doing.

    > Also interestingly, the only reference to the
    > bind:toObject:withKeyPath:options: method that comes up in an API
    > search of the documentation is from the NSKeyValueBindingCreation
    > protocol, which states this:
    >
    > "Establishes a binding between a given property of the receiver and
    > the property of a given object specified by a given key path."
    >
    > Since this doesn't seem to be actually the case, someone ought to
    > file a report on the documentation about this.

    Yeah, and the description of the "binding" parameter of that method
    also says it's a "key path for a property of the receiver", which
    contradicts my understanding (as we've been discussing).

    So, my curiosity piqued, I did some more reading.  The "Bindings"
    chapter of the Cocoa Fundamentals Guide <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals
    /CommunicatingWithObjects/chapter_6_section_6.html
    > also directly contradicts what I've been saying.  It unambiguously
    states that you can bind together any two objects so long as they're
    KVC/KVO-compliant.  Now _I'm_ confused -- and worried that I've been
    spreading misinformation.

    Time to build a test project...

    ... time passes ...

    OK.  So, from what I can see, bindings do work with just KVC/KVO, but
    they are inherently one-way.  That is, the following:

        [thing1 bind:@"property1" toObject:thing2
    withKeyPath:@"property2" options:nil];

    means that thing1's property1 should update itself with the value from
    thing2's property2 whenever thing2's property2 changes.  It does not
    imply that thing2's property2 will be updated if thing1's property1
    changes.  If you want that, then you should set it up explicitly:

        [thing2 bind:@"property2" toObject:thing1
    withKeyPath:@"property1" options:nil];

    From my brief testing, this does not produce infinitely looping
    mutual updates.

    However, it seems as though a binding name is _not_ a key path as
    described in the documentation; it's just a key.  Trying to use a key
    path resulted in exceptions.

    None of this jibes with bindings as they're used in views.  First,
    there's that reference listing the bindings supported by various
    classes.  As discussed, the list for NSTextField is decidedly shorter
    than the list of properties for which NSTextField is KVC/KVO-
    compliant.  That's generally true of most views listed in that
    reference.  Second, establishing a binding to a view is two-way, while
    establishing non-view bindings is one-way.

    It's odd that there's no clear, definitive statement about what
    happens when you bind the properties of two non-view, non-NSController-
    derived classes together.  As I said above, there is a definite
    statement that you can do it, just not what happens if you do.  The
    fact that bind:toObject:withKeyPath:options: is only documented as
    part of an informal protocol and not on NSObject itself implies that
    there's no default implementation, and yet there is.

    I'm quite perplexed.

    > Oh well, thanks for your patience with my questions.

    Thank you for your persistence in asking.  It's helped me learn, or at
    least unlearn. ;)

    Cheers,
    Ken
  • On Jun 28, 2008, at 2:55 AM, Ken Thomases wrote:
    >
    >
    >> Also interestingly, the only reference to the
    >> bind:toObject:withKeyPath:options: method that comes up in an API
    >> search of the documentation is from the NSKeyValueBindingCreation
    >> protocol, which states this:
    >>
    >> "Establishes a binding between a given property of the receiver and
    >> the property of a given object specified by a given key path."
    >>
    >> Since this doesn't seem to be actually the case, someone ought to
    >> file a report on the documentation about this.
    >
    > Yeah, and the description of the "binding" parameter of that method
    > also says it's a "key path for a property of the receiver", which
    > contradicts my understanding (as we've been discussing).
    >
    > So, my curiosity piqued, I did some more reading.  The "Bindings"
    > chapter of the Cocoa Fundamentals Guide <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals
    /CommunicatingWithObjects/chapter_6_section_6.html
    > > also directly contradicts what I've been saying.  It unambiguously
    > states that you can bind together any two objects so long as they're
    > KVC/KVO-compliant.  Now _I'm_ confused -- and worried that I've been
    > spreading misinformation.

    Note the terminology on that page:
    " You can establish a binding between an attribute of a view object
    and a property of a model object (typically through a mediating
    property of a controller object)."

    It refers to an "attribute", not a property or a key or key path. So I
    am guessing that's the difference here: views override NSObject's
    default property-based binding and replace it with an attribute-based
    one. This allows two-way syncing to occur and prevents loops. Views,
    since they allow the user to make changes, go the extra step of
    propagating the change to the model as part of their binding
    implementation. Regular non-view objects don't have this, so the
    binding is one-way. They use KVC to see changes in the model value but
    not to change the model value. Am I right?

    [Stuff snipped]

    >
    > None of this jibes with bindings as they're used in views.  First,
    > there's that reference listing the bindings supported by various
    > classes.  As discussed, the list for NSTextField is decidedly
    > shorter than the list of properties for which NSTextField is KVC/KVO-
    > compliant.  That's generally true of most views listed in that
    > reference.  Second, establishing a binding to a view is two-way,
    > while establishing non-view bindings is one-way.

    It's time for mmalc to chime in and put everyone straight.

    Steve Weller  <bagelturf...>
    Technical Writing, Editing, Developer Guides, and a little Cocoa
  • On Jun 28, 2008, at 4:55 AM, Ken Thomases wrote:

    > Yeah, and the description of the "binding" parameter of that method
    > also says it's a "key path for a property of the receiver", which
    > contradicts my understanding (as we've been discussing).
    >
    > So, my curiosity piqued, I did some more reading.  The "Bindings"
    > chapter of the Cocoa Fundamentals Guide <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals
    /CommunicatingWithObjects/chapter_6_section_6.html
    > > also directly contradicts what I've been saying.  It unambiguously
    > states that you can bind together any two objects so long as they're
    > KVC/KVO-compliant.  Now _I'm_ confused -- and worried that I've been
    > spreading misinformation.

    I wouldn't worry about that too much - everything you said seems to
    jibe perfectly with what views do - the text field's binding *is*
    called "value" and not "stringValue" (that was my bad), and there's no
    corresponding "value" instance method on NSTextView nor any of its
    superclasses, nor does running class-dump on the AppKit turn up a
    "value" method on any class in the AppKit except for
    _NSControllerKeyValuePair, whatever that is. So in the typical case of
    views, you'd seem to be correct that the bindings represent something
    other than properties, and live in a different namespace.

    However, NSObject does have a default implementation of
    bind:toObject:withKeyPath:options:, which must have some purpose.
    Setting up a two-way binding by running the binding twice does seem to
    work, although I don't know how "kosher" it is, and it does seem less
    than satisfactory to me as, like you mentioned, it doesn't seem to
    work with a key path for the first argument, making it necessary to
    take the controller out of the equation. So it's definitely probably
    better to override bind:toObject:withKeyPath:options: on the view, to
    allow for using a controller and having a cleaner implementation.

    After thinking about it a bit, though, I don't think infinite loops
    should be a problem, because my guess as to how the bindings work is
    that the willChangeValueForKey: method probably registers the object
    somewhere as being in the middle of setting that key, and then when
    the bindings system goes around looking for objects to set that key
    for, it would pass over the ones that have indicated they're already
    setting that key by calling willChangeValueForKey: I'd expect then
    that didChangeValueForKey: would clear that status (along with asking
    the bindings system to update any object that observes that key and
    hasn't called willChangeValueForKey: recently). So infinite loops
    shouldn't be much of a problem if I'm understanding this right.

    I think what we can all take home from this is that the documentation
    for bindings needs to be clearer and less self-contradictory on the
    very basic concept of exactly what Cocoa Bindings *is*.

    Charles
  • On Jun 28, 2008, at 4:55 AM, Ken Thomases wrote:

    > Yeah, it surprises me, too, that NSObject has an implementation of
    > bind:toObject:withKeyPath:options:.  I had thought that it was just
    > part of an informal protocol -- that is, that it was declared in a
    > category on NSObject, but never implemented except by specific
    > classes which adopted that protocol.  However, I did a symbol dump
    > of the AppKit framework and I see that there is, in fact, an
    > implementation.  I have no idea what it could be doing.

    Actually, I gave it a little thought, and perhaps the purpose of
    NSObject's default implementation is just to make it easier to
    implement the stuff that's mentioned in that "how bindings work"
    document. The built-in implementation provides the bindings in one
    direction for us - all we have to do is supply the bindings in the
    other direction, so adding an NSMutableDictionary instance variable to
    the view and then adding these methods:

    - (void)bind:(NSString *)key toObject:(id)obj withKeyPath:(NSString
    *)keyPath options:(NSDictionary *)options {
        NSDictionary *binding = [NSDictionary
    dictionaryWithObjectsAndKeys:key, @"key", obj, @"target", keyPath,
    @"keyPath", nil];

        [ivar_bindingsDict setObject:binding forKey:key];

        [super bind:key toObject:obj withKeyPath:keyPath options:options];
    }

    - (void)unbind:(NSString *)key {
        [ivar_bindingsDict removeObjectForKey:key];
    }

    - (void)fireNotificationsForKey:(NSString *)key {
        NSDictionary *binding = [ivar_bindingsDict objectForKey:key];

        if(binding) {
            id target = [binding objectForKey:@"target"];
            NSString *keyPath = [binding objectForKey:@"keyPath"];

            [target setValue:[self valueForKey:key] forKeyPath:keyPath];
        }
    }

    and then just calling [self fireNotificationsForKey:@"someKey"] each
    time you modify whatever it is in the view's state that will cause the
    binding "someKey" to need to be updated, would pretty much do it, am I
    right?

    (I suppose you'd also want to expose your available bindings by
    calling +exposeBinding: in your +initialize method and implement
    valueClassForBinding: if you're going to make an Interface Builder
    palette for your view)

    Charles
  • On Jun 28, 2008, at 10:17 AM, Charles Srstka wrote:

    > I think what we can all take home from this is that the
    > documentation for bindings needs to be clearer and less self-
    > contradictory on the very basic concept of exactly what Cocoa
    > Bindings *is*.

    For what it's worth, after sending my previous message, I did file a
    documentation enhancement request using the "It's good, but" link.
    Hopefully, I described my confusion and the several seemingly-
    contradictory implications of the documentation well enough to be
    useful to the good folks at Apple.

    Cheers,
    Ken
  • On Sat, Jun 28, 2008 at 4:17 PM, Charles Srstka
    <cocoadev...> wrote:

    > I wouldn't worry about that too much - everything you said seems to jibe
    > perfectly with what views do - the text field's binding *is* called "value"
    > and not "stringValue" (that was my bad), and there's no corresponding
    > "value" instance method on NSTextView nor any of its superclasses, nor does
    > running class-dump on the AppKit turn up a "value" method on any class in
    > the AppKit except for _NSControllerKeyValuePair, whatever that is. So in the
    > typical case of views, you'd seem to be correct that the bindings represent
    > something other than properties, and live in a different namespace.

    And if you consider the relationship between the "value" binding and
    the "objectValue" property, things get even more odd!

    You can programmatically bind to an NSTextField's (and presumably any
    other NSControl's) "objectValue" and achieve the same results as
    binding to its "value" (either programmatically or through IB).

    So you might think that NSControl has a "value" property, and simply
    binds it to its own "objectValue" (or vice versa). Except that you
    can't call "setValue" (or setValue:whatever forKey:@"value") on an
    NSControl, as you would expect to be able to if this were the case.

    Perhaps NSControls have their own bind:toObject:withKeyPath:options:
    implementation which simply checks for "value" and effectively binds
    to "objectValue"? No, classdump confirms that the only
    bind:toObject:withKeyPath:options: implementation is that of the
    NSKeyValueBindingCreation category of NSObject.

    Maybe it's the NSObject implementation itself which handles the
    special case? No, you can create an "objectValue" property on your own
    classes but you still can't bind to "value" on them (the error message
    complains "this class is not key value coding-compliant for the key
    value")

    It seems really wierd to me that this separate namespace exists,
    especially as the AppKit designers could just have exposed the
    "objectValue" binding directly rather than this "value" binding which
    seems to do exactly the same thing...

    Hamish
  • On Jun 29, 2008, at 11:30 PM, Hamish Allan wrote:

    > Perhaps NSControls have their own bind:toObject:withKeyPath:options:
    > implementation which simply checks for "value" and effectively binds
    > to "objectValue"? No, classdump confirms that the only
    > bind:toObject:withKeyPath:options: implementation is that of the
    > NSKeyValueBindingCreation category of NSObject.

    Wait, what? Okay, that contradicts the understanding that I had come
    to... so the built-in views establish two-way bindings *without*
    overriding bind:toObject:withKeyPath:options:? Great, that puts us
    back to square one!

    Is there some way to page mmalc to this thread? I think his input
    would be really helpful about now...

    Charles
  • On Mon, Jun 30, 2008 at 5:33 AM, Charles Srstka
    <cocoadev...> wrote:

    > Wait, what? Okay, that contradicts the understanding that I had come to...
    > so the built-in views establish two-way bindings *without* overriding
    > bind:toObject:withKeyPath:options:? Great, that puts us back to square one!

    It would seem so, but in fact I was mistaken about the equivalence
    between "value" and "objectValue" bindings: the binding to objectValue
    is only a one-way binding. I guess that difference would make it safer
    to use a separate namespace.

    Hamish
  • On Mon, Jun 30, 2008 at 12:38 AM, Hamish Allan <hamish...> wrote:
    > On Mon, Jun 30, 2008 at 5:33 AM, Charles Srstka
    > <cocoadev...> wrote:
    >
    >> Wait, what? Okay, that contradicts the understanding that I had come to...
    >> so the built-in views establish two-way bindings *without* overriding
    >> bind:toObject:withKeyPath:options:? Great, that puts us back to square one!
    >
    > It would seem so, but in fact I was mistaken about the equivalence
    > between "value" and "objectValue" bindings: the binding to objectValue
    > is only a one-way binding. I guess that difference would make it safer
    > to use a separate namespace.

    I am largely bindings clueless, so beware....

    NSObject's -bind:... method does two things. First, it sets up an
    automatic one-way binding from the model object to the view object.
    When the model is changed, the view's key is automatically set to the
    new value. Second, it sets up an info dictionary for that binding.

    Although Apple's sample code shows overriding -bind:... to store
    information about the new binding, it doesn't look like this is
    necessary. You can simply use -infoForBinding: to obtain the info
    dictionary, extract the bound object and key, and use that information
    to update the model object. I'd assume this is what the Apple classes
    do, and it seems to me to be a lot simpler than overriding -bind:...
    to stash away a bunch of information that's already being stored for
    you anyway.

    The reason the objectValue binding doesn't work both ways is because
    NSControl doesn't implement this kind of thing when its objectValue
    changes. You need to implement the view->model changes manually they
    don't come for free just because you're KVC compliant, and NSControl
    doesn't implement it for objectValue. You get the model->view
    direction for free with KVC complaince, which is why it halfway works.

    Mike
  • On Mon, Jun 30, 2008 at 3:56 PM, Michael Ash <michael.ash...> wrote:

    > Although Apple's sample code shows overriding -bind:... to store
    > information about the new binding, it doesn't look like this is
    > necessary. You can simply use -infoForBinding: to obtain the info
    > dictionary, extract the bound object and key, and use that information
    > to update the model object. I'd assume this is what the Apple classes
    > do, and it seems to me to be a lot simpler than overriding -bind:...
    > to stash away a bunch of information that's already being stored for
    > you anyway.

    That would seem a pretty reasonable assumption, but it doesn't seem to
    be the case. At least, breakpoints on -[NSTextField infoForBinding:],
    -[NSControl infoForBinding:],  -[NSObject infoForBinding:] don't seem
    to trigger when the text field is edited; nor are messages logged from
    a subclass of NSTextField overriding -infoForBinding:.

    Any other ideas, anyone?

    Thanks,
    Hamish
  • Sorry, I haven't read every message in this thread, but I think I can
    answer the original question

    > [[self bar] bind:@"title" toObject:ivar_controller
    > withKeyPath:@"selection.displayName" options:nil];
    >
    > Now here's the thing: if I call setDisplayName: on Foo, it calls
    > Bar's setTitle: method, exactly as it should. However, if I call
    > setTitle: on Bar, it does *not* end up calling Foo's setDisplayName:
    > method, although it seems like it should. I can change the
    > bind:toObject:withKeyPath:options: invocation above so that it binds
    > Bar directly to Foo without going through the object controller, or
    > I can try going the other way and binding the Foo to the Bar -
    > always I get the same result.

    Bindings of this type are one way. Their kinda ad hoc. "Title" will be
    updated to match ivar_controller.selection.displayName. Changing title
    will not result in any KVC calls to change anything in the
    ivar_controller. This is a read-only setup.

    It sounds like you're asking for 2 things.
    1) To have logic that will update ivarController.selection.displayName
    to match "title".
    2) To have the logic from #1 triggered when setTitle is called.

    There was some suggestion about using infoForBinding: to do blah blah
    blah.

    Yes! infoForBinding is what you should use to implement the logic in #1.

    // in Bar get the infoForBinding dictionary
    NSDictionary *info = [self infoForBinding:@"title"];

    // extract the controller and keypath info
    id controller = [info objectForKey:NSObservedObjectKey];
    NSString *keyPath = [info objectForKey:NSObservedKeyPathKey];

    // extra points for looking in the binding options for value
    transformers and stuff
    // options = [info  objectForKey:NSOptionsKey];

    // push/write the value to the controller
    [controller setValue:theTitle forKeyPath:keyPath];

    The trick to getting #2 is that setTitle is ALSO what gets called
    during the regular we-did-the-read-work-for-you bindings update from
    the controller. Don't let changing the displayName end up calling
    setTitle if setTitle's going to set the displayName. Make sense?

    So how do we fix this issue?

    2a) Don't use setTitle to trigger logic in #1. This is the approach I
    normally suggest. Your views should push these changes down due to
    user interaction, not programatic fiddling.

    2b) Implement the "read" logic yourself by implementing bind:. This
    means you'll need to cache the binding info yourself, start observing
    the controller object, and react to the KVO notifications
    appropriately. Don't call super for bind:/unbind:/infoForBinding:
    @"title".

    As a final note - I'm not sure if anyone else mentioned it. The
    original code snippets had stuff like

    - (void)setTitle:(NSString *)title {
        [self willChangeValueForKey:@"title"];

        NSLog(@"setting title to %@", title);

        if(title != ivar_title) {
            [ivar_title release];
            ivar_title = [title copy];
        }

        [self didChangeValueForKey:@"title"];
    }

    You don't need the will/did changeValueForKey:@"title" calls in the
    setTitle: method if you haven't disabled automatic KVO notifications
    for title. If you didn't know you could do that, then you haven't
    disabled KVO notifications for your class and, therefore, don't need
    to call will/did changeValueForKey:@"title".

    Hope that clears things up.

    On Jun 30, 2008, at 2:04 PM, Hamish Allan wrote:

    > On Mon, Jun 30, 2008 at 3:56 PM, Michael Ash <michael.ash...>
    > wrote:
    >
    >> Although Apple's sample code shows overriding -bind:... to store
    >> information about the new binding, it doesn't look like this is
    >> necessary. You can simply use -infoForBinding: to obtain the info
    >> dictionary, extract the bound object and key, and use that
    >> information
    >> to update the model object. I'd assume this is what the Apple classes
    >> do, and it seems to me to be a lot simpler than overriding -bind:...
    >> to stash away a bunch of information that's already being stored for
    >> you anyway.
    >
    > That would seem a pretty reasonable assumption, but it doesn't seem to
    > be the case. At least, breakpoints on -[NSTextField infoForBinding:],
    > -[NSControl infoForBinding:],  -[NSObject infoForBinding:] don't seem
    > to trigger when the text field is edited; nor are messages logged from
    > a subclass of NSTextField overriding -infoForBinding:.
    >
    > Any other ideas, anyone?
    >
    > Thanks,
    > Hamish

    --------------------------
    RONZILLA
  • On Mon, Jun 30, 2008 at 10:43 PM, Ron Lue-Sang <luesang...> wrote:

    > Yes! infoForBinding is what you should use to implement the logic in #1.
    > [...]
    > 2b) Implement the "read" logic yourself by implementing bind:.

    What puzzles me is that NSTextField doesn't seem to do either of
    these, yet still seems to know which key path to update after user
    interaction.

    Hamish
  • On Mon, Jun 30, 2008 at 5:04 PM, Hamish Allan <hamish...> wrote:
    > On Mon, Jun 30, 2008 at 3:56 PM, Michael Ash <michael.ash...> wrote:
    >
    >> Although Apple's sample code shows overriding -bind:... to store
    >> information about the new binding, it doesn't look like this is
    >> necessary. You can simply use -infoForBinding: to obtain the info
    >> dictionary, extract the bound object and key, and use that information
    >> to update the model object. I'd assume this is what the Apple classes
    >> do, and it seems to me to be a lot simpler than overriding -bind:...
    >> to stash away a bunch of information that's already being stored for
    >> you anyway.
    >
    > That would seem a pretty reasonable assumption, but it doesn't seem to
    > be the case. At least, breakpoints on -[NSTextField infoForBinding:],
    > -[NSControl infoForBinding:],  -[NSObject infoForBinding:] don't seem
    > to trigger when the text field is edited; nor are messages logged from
    > a subclass of NSTextField overriding -infoForBinding:.
    >
    > Any other ideas, anyone?

    Well, this is irrelevant to the question of what *you* should do.
    Using -infoForBinding: is simple and it works, so use it.

    However, if you're curious about what Apple does, it shouldn't be too
    hard to find out. You know one thing that happens reliably: your
    model's key is set. So set up a test app, put a breakpoint on the
    model's setter, then see what's calling it. The rest should follow
    from there.

    Mike
  • On Jun 30, 2008, at 2:53 PM, Hamish Allan wrote:

    > On Mon, Jun 30, 2008 at 10:43 PM, Ron Lue-Sang <luesang...>
    > wrote:
    >
    >> Yes! infoForBinding is what you should use to implement the logic
    >> in #1.
    >> [...]
    >> 2b) Implement the "read" logic yourself by implementing bind:.
    >
    > What puzzles me is that NSTextField doesn't seem to do either of
    > these, yet still seems to know which key path to update after user
    > interaction.
    >
    > Hamish

    Yep, that's right. The bindings machinery uses a faster cache. The
    same way as bindable-view implementors are free to cache the binding
    information any way you like. You don't need to use infoForBinding,
    but it's the easiest solution to describe.

    --------------------------
    RONZILLA
  • On Tue, Jul 1, 2008 at 12:56 AM, Michael Ash <michael.ash...> wrote:

    > However, if you're curious about what Apple does, it shouldn't be too
    > hard to find out. You know one thing that happens reliably: your
    > model's key is set. So set up a test app, put a breakpoint on the
    > model's setter, then see what's calling it. The rest should follow
    > from there.

    This gets you into a whole world of wondering why _NSBindingAdapter,
    NSValueBinder, NSBinder etc. exist. I think I'll leave that for now!

    I do wonder, incidentally, why the NSKeyValueBindingCreation category
    of NSObject is in AppKit rather than Foundation.

    Hamish
  • Hi,

    Regarding the whole asymmetry between the one-way bindings between
    arbitrary KVC/KVO-compliant properties on the one hand and the two-way
    bindings supported by views and NSController-derived objects on the
    other hand, I think I figured something out.

    The documentation makes, in a few places, a distinction between the
    terms "key-value bindings" (KVB) and "Cocoa bindings".  In fact, Cocoa
    bindings are described as being built on KVC, KVO, _and KVB_:

    From "What Are Cocoa Bindings?" <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Con
    cepts/WhatAreBindings.html
    >:

    > [This article] gives a conceptual overview of how the main
    > technologies that underpin Cocoa bindings—key-value coding, key-
    > value observing, and key-value binding—work, and how they inter-
    > relate.

    From "How Do Bindings Work?" <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Con
    cepts/HowDoBindingsWork.html
    >:

    > Cocoa bindings rely on other technologies—key-value coding (KVC) and
    > key-value observing (KVO)—to communicate changes between objects,
    > and on key-value binding (KVB) to bind a value in one object to a
    > property in another.

    From "Cocoa Fundamentals Guide: Bindings" <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals
    /CommunicatingWithObjects/chapter_6_section_6.html
    >:

    > The implementation of bindings rests on the enabling mechanisms of
    > key-value coding, key-value observing, and key-value binding.

    So, it seems like my confusion was in thinking there was only one kind
    of binding supported by Cocoa, when there are two which are
    confusingly-similarly-named.  Adding to the confusion is that the
    documentation tends to refer to "binding(s)" with neither prefix, and
    which it means is not always clear from the context.

    KVB is a generic capability that you get with the
    bind:toObject:withKeyPath:options: method for most classes.  It is one-
    way updating of a KVC-compliant property on the receiver from a KVC/
    KVO-compliant property at the key-path from the named object.

    In addition, some framework classes supply additional functionality on
    top of that -- Cocoa bindings.  The functioning of this kind of
    binding is radically different, even though it still uses
    bind:toObject:withKeyPath:options: as its interface.  As discussed,
    the name of a Cocoa binding need not be a property of the receiver.
    (It's often referred to as an "attribute".)  Also, it's two-way.

    I think this subtle distinction in terminology needs to be called out
    more forcefully in the documentation.  Also, there should be
    documentation on NSObject as to what
    bind:toObject:withKeyPath:options: does in its default implementation
    (one-way property update), and possibly separate documentation on
    NSView and NSController about the separate behavior that those classes
    provide for the same method.  The fact that that method is currently
    only documented on an informal protocol is misleading.  It suggested
    (at least to me) that there was no default implementation, and one had
    to override it as illustrated in "How Do Bindings Work?" for it to do
    anything at all.  I did eventually find this:

    From "NSKeyValueBindingCreation Protocol Reference" <http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Pro
    tocols/NSKeyValueBindingCreation_Protocol/
    >:

    > This informal protocol is implemented by NSObject and its methods
    > can be overridden by view and controller subclasses.

    but that leaves a lot unsaid.

    Cheers,
    Ken
  • Key value Binding and Cocoa Bindings are the same thing.

    Key-Value Binding is implemented at the foundation level.  Cocoa
    Bindings is the name used for the additional features (controllers,
    views that support bindings, etc..) which is implemented at the AppKit
    level.

    So there is no distinction.

    On Jul 2, 2008, at 5:14 AM, Ken Thomases wrote:

    > Hi,
    >
    > Regarding the whole asymmetry between the one-way bindings between
    > arbitrary KVC/KVO-compliant properties on the one hand and the two-
    > way bindings supported by views and NSController-derived objects on
    > the other hand, I think I figured something out.
    >
    > The documentation makes, in a few places, a distinction between the
    > terms "key-value bindings" (KVB) and "Cocoa bindings".  In fact,
    > Cocoa bindings are described as being built on KVC, KVO, _and KVB_:
    >
    > From "What Are Cocoa Bindings?" <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Con
    cepts/WhatAreBindings.html
    > >:
    >
    >> [This article] gives a conceptual overview of how the main
    >> technologies that underpin Cocoa bindings—key-value coding, key-
    >> value observing, and key-value binding—work, and how they inter-
    >> relate.
    >
    >
    > From "How Do Bindings Work?" <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Con
    cepts/HowDoBindingsWork.html
    > >:
    >
    >> Cocoa bindings rely on other technologies—key-value coding (KVC)
    >> and key-value observing (KVO)—to communicate changes between
    >> objects, and on key-value binding (KVB) to bind a value in one
    >> object to a property in another.
    >
    > From "Cocoa Fundamentals Guide: Bindings" <http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals
    /CommunicatingWithObjects/chapter_6_section_6.html
    > >:
    >
    >> The implementation of bindings rests on the enabling mechanisms of
    >> key-value coding, key-value observing, and key-value binding.
    >
    >
    > So, it seems like my confusion was in thinking there was only one
    > kind of binding supported by Cocoa, when there are two which are
    > confusingly-similarly-named.  Adding to the confusion is that the
    > documentation tends to refer to "binding(s)" with neither prefix,
    > and which it means is not always clear from the context.
    >
    > KVB is a generic capability that you get with the
    > bind:toObject:withKeyPath:options: method for most classes.  It is
    > one-way updating of a KVC-compliant property on the receiver from a
    > KVC/KVO-compliant property at the key-path from the named object.
    >
    > In addition, some framework classes supply additional functionality
    > on top of that -- Cocoa bindings.  The functioning of this kind of
    > binding is radically different, even though it still uses
    > bind:toObject:withKeyPath:options: as its interface.  As discussed,
    > the name of a Cocoa binding need not be a property of the receiver.
    > (It's often referred to as an "attribute".)  Also, it's two-way.
    >
    >
    > I think this subtle distinction in terminology needs to be called
    > out more forcefully in the documentation.  Also, there should be
    > documentation on NSObject as to what
    > bind:toObject:withKeyPath:options: does in its default
    > implementation (one-way property update), and possibly separate
    > documentation on NSView and NSController about the separate behavior
    > that those classes provide for the same method.  The fact that that
    > method is currently only documented on an informal protocol is
    > misleading.  It suggested (at least to me) that there was no default
    > implementation, and one had to override it as illustrated in "How Do
    > Bindings Work?" for it to do anything at all.  I did eventually find
    > this:
    >
    > From "NSKeyValueBindingCreation Protocol Reference" <http://developer.apple.com/documentation/Cocoa/Reference/ApplicationKit/Pro
    tocols/NSKeyValueBindingCreation_Protocol/
    > >:
    >
    >> This informal protocol is implemented by NSObject and its methods
    >> can be overridden by view and controller subclasses.
    >
    > but that leaves a lot unsaid.
    >
    > Cheers,
    > Ken
  • On Wed, Jul 2, 2008 at 5:31 PM, Scott Anguish <scott...> wrote:

    > Key value Binding and Cocoa Bindings are the same thing.
    >
    > Key-Value Binding is implemented at the foundation level.  Cocoa Bindings is
    > the name used for the additional features (controllers, views that support
    > bindings, etc..) which is implemented at the AppKit level.
    >
    > So there is no distinction.

    This is a rather unuseful attitude to take. Clearly, this thread
    started as a result of the distinction. Also, Apple's own
    documentation disagrees with you, as it states that Cocoa bindings are
    built on KVB. Ken's synopsis is right on the mark. I'd go even further
    and say that two-way binding ought to use a separate selector to make
    the distinction clear. There is already *far too much* hidden magic in
    bindings.

    Furthermore, bind:toObject:withKeyPath:options: is implemented in a
    category of NSObject in AppKit.framework, not at the Foundation level.
    I agree with you that it should be in the latter, though!

    Hamish
  • On Jul 2, 2008, at 4:04 PM, Hamish Allan wrote:

    > This is a rather unuseful attitude to take. Clearly, this thread
    > started as a result of the distinction. Also, Apple's own
    > documentation disagrees with you, as it states that Cocoa bindings are
    > built on KVB.
    >
    No, it doesn't.

    "Cocoa bindings" is an abstract term that refers to a collection of
    technologies that used together keep views, controllers, and models
    synchronised.
    Key-value binding is one of those technologies.
    There are not "two different kinds of binding".

    mmalc
  • On Jul 2, 2008, at 7:04 PM, Hamish Allan wrote:

    > On Wed, Jul 2, 2008 at 5:31 PM, Scott Anguish <scott...>
    > wrote:
    >
    >> Key value Binding and Cocoa Bindings are the same thing.
    >>
    >> Key-Value Binding is implemented at the foundation level.  Cocoa
    >> Bindings is
    >> the name used for the additional features (controllers, views that
    >> support
    >> bindings, etc..) which is implemented at the AppKit level.
    >>
    >> So there is no distinction.
    >
    > This is a rather unuseful attitude to take. Clearly, this thread

    > started as a result of the distinction.

    It may have started from that, but there is no distinction. they are
    the same technology.  KVB is the protocol, Cocoa Bindings is the term
    used to describe the complete set of features, including the
    controller and view objects.

    > Also, Apple's own
    > documentation disagrees with you, as it states that Cocoa bindings are
    > built on KVB.

    It was never intended to even hint that they were separate things.
    They are one and the same.

    <excerpt>
    The NSKeyValueBindingCreation informal protocol provides methods to
    create and remove bindings between view objects and controllers or
    controllers and model objects. In addition, it provides a means for a
    view subclass to advertise the bindings that it exposes. This informal
    protocol is implemented by NSObject and its methods can be overridden
    by view and controller subclasses.

    </excerpt>

    Binding directly between objects other than those was at the time that
    was written (and IMHO should still be) discouraged. There is still
    difference of opinion on whether that should be the case.

    > Ken's synopsis is right on the mark. I'd go even further
    > and say that two-way binding ought to use a separate selector to make
    > the distinction clear. There is already *far too much* hidden magic in
    > bindings.
    >
    > Furthermore, bind:toObject:withKeyPath:options: is implemented in a
    > category of NSObject in AppKit.framework, not at the Foundation level.
    > I agree with you that it should be in the latter, though!

    Yes, I screwed this up and immediately realized it when I was away
    from the machine.
  • On Thu, Jul 3, 2008 at 1:12 AM, mmalc crawford <mmalc_lists...> wrote:
    >
    > On Jul 2, 2008, at 4:04 PM, Hamish Allan wrote:
    >
    >> This is a rather unuseful attitude to take. Clearly, this thread
    >> started as a result of the distinction. Also, Apple's own
    >> documentation disagrees with you, as it states that Cocoa bindings are
    >> built on KVB.
    >>
    > No, it doesn't.

    No, really, it does! Read Ken's post again: he links to docs that talk
    of Cocoa bindings "relying on" KVB, and KVB being one of the main
    technologies "underpinning" Cocoa bindings. You yourself make pretty
    much the same distinction:

    > "Cocoa bindings" is an abstract term that refers to a collection of
    > technologies that used together keep views, controllers, and models
    > synchronised.
    > Key-value binding is one of those technologies.

    > There are not "two different kinds of binding".

    If that is the case, let me ask: is KVB unidirectional or bi-directional?

    Hamish
  • On Jul 7, 2008, at 3:51 PM, Hamish Allan wrote:

    > If that is the case, let me ask: is KVB unidirectional or bi-
    > directional?

    Whether a binding is unidirectional or bidirectional depends upon the
    specific binding in question and the meaning the class providing it
    has decided to give it.

      -- Chris
  • *sigh*

    I haven't looked at these docs recently. With that in mind, here's how
    I think of things…

    YES: Cocoa Bindings ®™ is built on KVC, KVO and KVB

    KVB is an informal protocol. So Cocoa Bindings™® provides a concrete
    implementation (on NSObject) of the KVB protocols.

    In addition to providing a KVB implementation, Cocoa Bindings®™ adds a
    set of reusable controllers to Cocoa.

    None of this really matters if you ask me. Did you ask me?

    The NSKeyValueBindingCreation protocol itself doesn't explicitly
    specify whether bindings are unidirectional or bidirectional.  Many of
    the bindings implemented by Cocoa Bindings®™ are implemented for
    specific Cocoa views (and the Cocoa Bindings®™ provided controllers).
    Many of these bindings happen to be bi-directional. Yay.

    Cocoa Binding™® also happens to provide a super generic implementation
    of NSKeyValueBindingCreation protocols so that even if you bind
    something that isn't "exposed" as a binding (like, you wouldn't see it
    in the object's exposedBindings list), something useful still happens.

    Are there two different kinds of bindings? Without getting too
    philosophical, I don't think there are. Hamish, what are the two types
    you're thinking of?

    On Jul 7, 2008, at 3:51 PM, Hamish Allan wrote:

    > On Thu, Jul 3, 2008 at 1:12 AM, mmalc crawford <mmalc_lists...>
    > wrote:
    >>
    >> On Jul 2, 2008, at 4:04 PM, Hamish Allan wrote:
    >>
    >>> This is a rather unuseful attitude to take. Clearly, this thread
    >>> started as a result of the distinction. Also, Apple's own
    >>> documentation disagrees with you, as it states that Cocoa bindings
    >>> are
    >>> built on KVB.
    >>>
    >> No, it doesn't.
    >
    > No, really, it does! Read Ken's post again: he links to docs that talk
    > of Cocoa bindings "relying on" KVB, and KVB being one of the main
    > technologies "underpinning" Cocoa bindings. You yourself make pretty
    > much the same distinction:
    >
    >> "Cocoa bindings" is an abstract term that refers to a collection of
    >> technologies that used together keep views, controllers, and models
    >> synchronised.
    >> Key-value binding is one of those technologies.
    >
    >> There are not "two different kinds of binding".
    >
    > If that is the case, let me ask: is KVB unidirectional or bi-
    > directional?
    >
    > Hamish

    --------------------------
    RONZILLA
  • If you feel that the bindings doc is unclear about this, thats one
    thing to claim, and something to file a bug about. I can't guarantee
    that it'll change though. I've never heard the argument that we have
    two different types of bindings before this thread.

    but if you're arguing with mmalc and I that we don't know what the doc
    says, I can assure you we both do.

    It's now been explained that we don't have two different types of
    bindings by the people who wrote that doc, and one of the engineers
    that works on the implementation.

    I'm unsure why this thread even started up again.

    On Jul 7, 2008, at 6:51 PM, Hamish Allan wrote:

    > On Thu, Jul 3, 2008 at 1:12 AM, mmalc crawford <mmalc_lists...>
    > wrote:
    >>
    >> On Jul 2, 2008, at 4:04 PM, Hamish Allan wrote:
    >>
    >>> This is a rather unuseful attitude to take. Clearly, this thread
    >>> started as a result of the distinction. Also, Apple's own
    >>> documentation disagrees with you, as it states that Cocoa bindings
    >>> are
    >>> built on KVB.
    >>>
    >> No, it doesn't.
    >
    > No, really, it does! Read Ken's post again: he links to docs that talk
    > of Cocoa bindings "relying on" KVB, and KVB being one of the main
    > technologies "underpinning" Cocoa bindings. You yourself make pretty
    > much the same distinction:
  • On Tue, Jul 8, 2008 at 5:29 AM, Ron Lue-Sang <luesang...> wrote:

    > KVB is an informal protocol. So Cocoa Bindings™(R) provides a concrete
    > implementation (on NSObject) of the KVB protocols.
    > In addition to providing a KVB implementation, Cocoa Bindings(R)™ adds a set
    > of reusable controllers to Cocoa.

    The penny drops! Thank you, Ron.

    The docs (http://developer.apple.com/documentation/Cocoa/Conceptual/CocoaBindings/Con
    cepts/WhatAreBindings.html
    ),
    in answer to the question "What Is A Binding?", state that "a binding
    is an attribute of one object that may be bound to a property in
    another such that a change in either one is reflected in the other."

    But there is also another type of binding, which I have since found
    referred to in the docs as "Read-Only"
    (http://developer.apple.com/documentation/Cocoa/Reference/CocoaBindingsRef/C
    oncepts/BindingTypes.html
    ),
    in which the change is only reflected in one direction. NSObject
    provides an implementation of this, which I had previously thought of
    as a "pure" key-value binding, whereas I thought of the description
    above as referring to "Cocoa bindings" (partly because if I were
    writing the two-way implementation, I would build it atop the
    unidirectional implementation, just as the docs state that Cocoa
    Bindings are built on KVB). But I now understand that both types of
    bindings are actually Cocoa Bindings.

    Scott, for what it's worth, I really don't agree with you that Cocoa
    Bindings and KVB are "the same thing" or that "there is no
    distinction". I now understand that they are not two different types
    of bindings: indeed, that neither of them is a type of binding. But if
    you're wondering why this thread has gone on for longer than it should
    have done, it's partly because your repeated assertion of their
    equivalence has drawn my attention away from what your colleagues have
    been trying to point out to me: that KVB is merely the informal
    protocol, whereas the various implementations (and what I would call
    "types" of binding) are all provided by Cocoa Bindings(R)™.

    Thank you also to everyone else who replied.

    Hamish
  • On Jul 8, 2008, at 11:33 AM, Hamish Allan wrote:

    > Scott, for what it's worth, I really don't agree with you that Cocoa
    > Bindings and KVB are "the same thing" or that "there is no
    > distinction".

    Ron just said the same thing.

    > I now understand that they are not two different types
    > of bindings: indeed, that neither of them is a type of binding. But if
    > you're wondering why this thread has gone on for longer than it should
    > have done, it's partly because your repeated assertion of their
    > equivalence has drawn my attention away from what your colleagues have
    > been trying to point out to me: that KVB is merely the informal
    > protocol, whereas the various implementations (and what I would call
    > "types" of binding) are all provided by Cocoa Bindings(R)™.
    >

    I think it was the first response I made in this thread I quoted the
    NSKeyValueBindingCreation protocol reference doc, which says, in its
    first paragraph:

    The NSKeyValueBindingCreation __informal protocol__ provides methods
    to create and remove bindings between view objects and controllers or
    controllers and model objects. In addition, it provides a means for a
    view subclass to advertise the bindings that it exposes. This informal
    protocol is implemented by NSObject and its methods can be overridden
    by view and controller subclasses.

    Everything Ron said is right there in that paragraph.

    I don't understand how anything I've said could draw your attention
    away from anything mmalc or Ron said. We've all been repeating the
    same thing.
  • On Wed, Jul 9, 2008 at 2:43 AM, Scott Anguish <scott...> wrote:
    >
    > On Jul 8, 2008, at 11:33 AM, Hamish Allan wrote:
    >
    >> Scott, for what it's worth, I really don't agree with you that Cocoa
    >> Bindings and KVB are "the same thing" or that "there is no
    >> distinction".
    >
    > Ron just said the same thing.

    If you honestly think that an informal protocol and its implementation
    are the same thing, and that X and a proper subset of X are the same
    thing, then I can see how you might arrive at that conclusion.
    Otherwise, I am baffled.

    > Everything Ron said is right there in that paragraph.

    How can you say that, when it doesn't even mention Cocoa Bindings?

    > I don't understand how anything I've said could draw your attention away
    > from anything mmalc or Ron said. We've all been repeating the same thing.

    No. Specifically, neither of them have ever claimed that Cocoa
    Bindings and KVB are the same thing.

    Hamish
  • On Jul 8, 2008, at 9:39 PM, Hamish Allan wrote:

    > On Wed, Jul 9, 2008 at 2:43 AM, Scott Anguish <scott...>
    > wrote:
    >>
    >> On Jul 8, 2008, at 11:33 AM, Hamish Allan wrote:
    >>
    >>> Scott, for what it's worth, I really don't agree with you that Cocoa
    >>> Bindings and KVB are "the same thing" or that "there is no
    >>> distinction".
    >>
    >> Ron just said the same thing.
    >
    > If you honestly think that an informal protocol and its implementation
    > are the same thing, and that X and a proper subset of X are the same
    > thing, then I can see how you might arrive at that conclusion.
    > Otherwise, I am baffled.
    >
    >> Everything Ron said is right there in that paragraph.
    >
    > How can you say that, when it doesn't even mention Cocoa Bindings?
    >
    >> I don't understand how anything I've said could draw your attention
    >> away
    >> from anything mmalc or Ron said. We've all been repeating the same
    >> thing.
    >
    > No. Specifically, neither of them have ever claimed that Cocoa
    > Bindings and KVB are the same thing.
    >

    This has gone too far -- you're monstrously misrepresenting what Scott
    wrote.

    On Jul 8, 2008, at 8:33 AM, Hamish Allan wrote:

    > But if you're wondering why this thread has gone on for longer than
    > it should
    > have done, it's partly because your repeated assertion of their
    > equivalence has drawn my attention away from what your colleagues have
    > been trying to point out to me: that KVB is merely the informal
    > protocol, whereas the various implementations (and what I would call
    > "types" of binding) are all provided by Cocoa Bindings(R)™.
    >
    Before Scott posted his first, this thread had 25 messages whose
    content could perhaps be most charitably equated to a debate about the
    number of angels that could fit on a pinhead.  It culminated in this
    bizarre assertion that there were *two types of binding*:

    On Jul 2, 2008, at 5:14 AM, Ken Thomases wrote:
    > Regarding the whole asymmetry between the one-way bindings between
    > arbitrary KVC/KVO-compliant properties on the one hand and the two-
    > way bindings supported by views and NSController-derived objects on
    > the other hand, I think I figured something out.
    > The documentation makes, in a few places, a distinction between the
    > terms "key-value bindings" (KVB) and "Cocoa bindings".  In fact,
    > Cocoa bindings are described as being built on KVC, KVO, _and KVB_:
    >

    [...]

    >
    > So, it seems like my confusion was in thinking there was only one
    > kind of binding supported by Cocoa, when there are two which are
    > confusingly-similarly-named.  Adding to the confusion is that the
    > documentation tends to refer to "binding(s)" with neither prefix,
    > and which it means is not always clear from the context.
    >
    > KVB is a generic capability that you get with the
    > bind:toObject:withKeyPath:options: method for most classes.  It is
    > one-way updating of a KVC-compliant property on the receiver from a
    > KVC/KVO-compliant property at the key-path from the named object.
    >
    > In addition, some framework classes supply additional functionality
    > on top of that -- Cocoa bindings. The functioning of this kind of
    > binding is radically different, even though it still uses
    > bind:toObject:withKeyPath:options: as its interface.  As discussed,
    > the name of a Cocoa binding need not be a property of the receiver.
    > (It's often referred to as an "attribute".)  Also, it's two-way.

    and it was to this that Scott replied:

    > Key value Binding and Cocoa Bindings are the same thing.
    > Key-Value Binding is implemented at the foundation level.[sic --
    > Scott admitted the error later, but it's not relevant to the
    > issue.]  Cocoa Bindings is the name used for the additional features
    > (controllers, views that support bindings, etc..) which is
    > implemented at the AppKit level.
    > So there is no distinction.

    Note in particular the middle sentences: These make precisely the same
    point that Ron and I have made, and that you're asserting Scott did not.

    Scott later repeated the same point:

    On Jul 2, 2008, at 5:13 PM, Scott Anguish wrote:
    > It may have started from that, but there is no distinction. they are
    > the same technology.  KVB is the protocol, Cocoa Bindings is the
    > term used to describe the complete set of features, including the
    > controller and view objects.
    >

    Scott further made the context -- Ken's original flawed analysis --
    clear:

    On Jul 8, 2008, at 3:11 AM, Scott Anguish wrote:
    > It's now been explained that we don't have two different types of
    > bindings by the people who wrote that doc, and one of the engineers
    > that works on the implementation.
    >

    So, apropos of:

    > If you honestly think that an informal protocol and its implementation
    > are the same thing, and that X and a proper subset of X are the same
    > thing, then I can see how you might arrive at that conclusion.
    > [...]
    > No. Specifically, neither of them have ever claimed that Cocoa
    > Bindings and KVB are the same thing.
    >
    Scott has never made either claim.

    This thread has now run way past any conceivable utility it may have
    had; if you have any further comments, and in particular any further
    ad hominems against Scott, *please take them off-list*.

    mmalc
  • On Jul 9, 2008, at 12:39 AM, Hamish Allan wrote:

    > On Wed, Jul 9, 2008 at 2:43 AM, Scott Anguish <scott...>
    > wrote:
    >>
    >> On Jul 8, 2008, at 11:33 AM, Hamish Allan wrote:
    >>
    >>> Scott, for what it's worth, I really don't agree with you that Cocoa
    >>> Bindings and KVB are "the same thing" or that "there is no
    >>> distinction".
    >>
    >> Ron just said the same thing.
    >
    > If you honestly think that an informal protocol and its implementation
    > are the same thing, and that X and a proper subset of X are the same
    > thing, then I can see how you might arrive at that conclusion.
    > Otherwise, I am baffled.
    >

    This is a misrepresentation (yet again). To go back to the point where
    this all started.

    There are not two different bindings technologies with confusingly
    similar names (Cocoa Bindings and Key-Value Binding).

    There is one, it's all Cocoa Bindings.

    and now I'm going to pull out the moderator hammer and close the thread.
  • In subsequent discussion off-list, Mmalc has made it known to me that
    in questioning Scott's statements that Key-Value Binding and Cocoa
    Bindings are the same thing -- or rather, in failing to capitulate to
    his insistence that Ron made the identical claim -- I have caused him
    considerable physical and mental distress, undermined his character,
    brought him into disrepute, defamed him, devalued him, and damaged
    him; and that my behaviour was inexcusable, contemptible,
    reprehensible and truly obnoxious.

    I had no idea that it was possible to cause such calamity to a
    person's reputation simply by disagreeing with them in a public forum;
    let alone to cause them physical distress by doing so. I must
    therefore apologise for this, and implore anyone reading the thread to
    allay mmalc's concerns by making up their own mind rather than
    arbitrarily choosing my interpretation of events over Scott's.

    Hamish

    On Wed, Jul 2, 2008 at 5:31 PM, Scott Anguish <scott...> wrote:

    > Key value Binding and Cocoa Bindings are the same thing.
    >
    > Key-Value Binding is implemented at the foundation level.  Cocoa Bindings is
    > the name used for the additional features (controllers, views that support
    > bindings, etc..) which is implemented at the AppKit level.
    >
    > So there is no distinction.
  • Your message is entirely off topic and totally inappropriate.

    I can't see how anyone on the list could feel this was an appropriate
    response.

    On Jul 13, 2008, at 5:06 PM, Hamish Allan wrote:

    > <snip private information>

    This isn't relevant and is personal information that should not be
    posted.. Whether about me, or someone else, this will absolute NOT be
    tolerated.

    >> I had no idea that it was possible to cause such calamity to a
    >> person's reputation simply by disagreeing with them in a public
    >> forum;

    Continued misrepresentation of ANY list user's position, is
    inappropriate. Disagreement is not.

    >>
    >> let alone to cause them physical distress by doing so. I must
    >> therefore apologise for this, and implore anyone reading the thread
    >> to
    >> allay mmalc's concerns by making up their own mind rather than
    >> arbitrarily choosing my interpretation of events over Scott's.

    This is harassment, plain and simple.

    Behavior such as this is not appropriate for any forum.

    This thread is closed.
previous month june 2008 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30            
Go to today
MindNode
MindNode offered a free license !