Cocoa Bindings to a CALayer position's values

Q: Can I setup a Cocoa Binding to "CALayer.position.x" and "CALayer.position.y?"

A: No, because a CGPoint is not an object, it's a basic struct, and as such is not compatible with Key Value Coding / Observing. You can bind to the position itself, you just can't bind to the x and y values inside the position. If you find yourself wanting to do this, here is how to work around it and, in the process, make your code cleaner and easier to read.

Setup a Core Data managed object that has x and y values as attributes. The initial reaction is to bind the managed object's x and y values to the CALayer.position's x and y values. This won't work for the reason described above. You need to add a position property to the managed object so it can bind managedObject.position to CALayer.position. Both of these are KVC compliant, so everything works as you would expect.

Add the property declaration for position in the managed object's header file.

@interface MovablePiece : NSManagedObject

@property (nonatomic, retain) NSNumber * y;
@property (nonatomic, retain) NSNumber * x;
@property (nonatomic) CGPoint position;

@end

This wraps the x and y values to create a CGPoint.

@implementation MovablePiece

@dynamic y;
@dynamic x;

- (CGPoint)position {
  return CGPointMake(self.x.doubleValue, self.y.doubleValue);
}

- (void)setPosition:(CGPoint)newValue {
  self.x = @(newValue.x);
  self.y = @(newValue.y);
}

@end

It's as easy as that. As a side effect, this really improves the code everywhere else in the app. Instead of having this:

piece.x = @(2);
piece.y = @(4);

You have the much more instructive:

piece.position = CGPointMake(2, 4);

It's easy to start writing code from the bottom up and forget to properly encapsulate your data, which leads to messy code trying to abuse a system like Cocoa Bindings. When you run into a wall like this, try looking at the problem from the top down and see what you want to do from the interface side of things, not from the implementation side. The answer will usually be staring you in the face.

Question or Comment?