Cocoa bindings not updating in reverse

220 views Asked by At

I'm trying to understand the directionality of Cocoa bindings. In particular, I've written this little program to demonstrate bindings, and I'm not sure why it outputs what it does. Here is the program:

@interface SimpleClass : NSObject
@property (retain) NSString *s; 
@end

@implementation SimpleClass
@end

int main(int argc, char *argv[]) {
    SimpleClass *simpleClass1 = [[SimpleClass alloc] init];
    SimpleClass *simpleClass2 = [[SimpleClass alloc] init];

    [simpleClass1 bind:@"s" toObject:simpleClass2 withKeyPath:@"s" options:nil];

    //[simpleClass1 willChangeValueForKey:@"s"];
    simpleClass1.s = @"Hello, World!";
    //[simpleClass1 didChangeValueForKey:@"s"];

    NSLog(@"%@", simpleClass1.s);
    NSLog(@"%@", simpleClass2.s);

    simpleClass2.s = @"Something else!";

    NSLog(@"%@", simpleClass1.s);
    NSLog(@"%@", simpleClass2.s);

    return 0;
}

When I run this program, the output is:

Hello, World!
(null)
Something else!
Something else!

This leads me to believe that bindings are unidirectional. However, I've come across this and this that both seem to say that bindings should be bidirectional (though neither is very clear). Uncommenting the willChangeValueForKey and didChangeValueForKey lines doesn't affect the output.

Am I correct in my conclusion that bindings are unidirectional? Or is there some way to specify at binding creation time that it should be bidirectional?

1

There are 1 answers

0
Ken Thomases On BEST ANSWER

The default implementation of bindings in NSObject is unidirectional. The bindings are effectively read-only.

Other Cocoa classes override all or part of the default implementation to provide more powerful features. Apple's guide to how to do that in your own classes is here. Mind you, I don't think any of Cocoa's classes implement bindings quite that way.

Also check out the discussion of message flow in bindings.

Note that, because a class can implement the NSKeyValueBindingCreation protocol how it wants, a binding name does not necessarily correspond to a property. For example, NSTextField has a "value" binding, but does not have a "value" property (there's no getter or setter that conforms to the key-value coding naming conventions for such a property).

The fact that the default implementation provided by NSObject does happen to use KVC to set a property with the same name as the binding on the object which was bound when the bound-to object's property changes is specific to that implementation. Of course, anything which doesn't override that implementation will inherit it, but some classes do override it.