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?
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.