In my project, I usually have a composite object (GameObject) that needs to expose a few properties of an ivar into the GameObject’s interface. For example, a GameObject has a Sprite with a ‘position’ property, and I want to use the Sprite’s position as a property of the GameObject. This is easy enough with:
// GameObject.h
@interface GameObject : NSObject
@property CGPoint position;
...
@end
// GameObject.m
@interface GameObject ()
@property Sprite* sprite; // private property
@end
@implementation
- (CGPoint)position { return sprite.position; };
- (void)setPosition:(CGPoint)p { sprite.position = p; };
...
As a side project, I have been looking at generating the getter/setter with a C macro. Ideally I would be able to do:
@implementation
EXPOSE_SUBCOMPONENT_PROPERTY(subcomponent,propertyName,propertyType);
...
My latest failed attempt is:
#define EXPOSE_SUBCOMPONENT_PROPERTY(sub,property,type) \
- (type)property { id x = sub; return x.##property;} \
- (void)setProperty:(type)set_val { id x = sub; x.##property = set_val; } \
Any macro wizards out there able to help out?
Secondly, is there a way to not need to supply the type of the property to the macro?
Found a better solution. The trick was understanding how symbols are split up, to properly use ‘##’. Also, had to add a macro for the property declaration to customize the getter/setter names, which gets around the issue of capitalizing the name of the property. Not a big deal for me, helps me remember its a special property. The only downsize I can think of is they won’t be KVO compliant because of the custom name.
I renamed the macros to make them easier to remember (they substitute for a @property and @synthesize respectively), and rearranged the argument order to mirror a property.
Another version, makes @property declarations more natural, and has the added bonus of being able to a property at any depth (rather than just ivar properties, you can reach down to ivar.property.another_property.indefinitely). You can also set the name of the property to be different from its name in the composed object.
Example use: