Use categories in Objective C to add instance variables to a CCSprite or anything else

Ok, I’ve got this down to about 10 lines of code.

I’ve got some button sprites in Cocos2D that need an instance variable.  I’m already using userData, and found that I was starting to overload it to use it the text in there for more than one purpose… if you start stripping off substrings from the userData to code for things, you might be interested in having another instance variable.

So you want to add “.mydata” to your sprites?  Try this:

1.  Decide where you want the scope of this.  In my app, there’s only one scene with one layer, and so in the MyLayer.m file where all my button sprites are, I’m adding this code at the top, just above the @interface MyLayer line:

@interface CCSprite (MyExtras)
@property (nonatomic,retain) id mydata;
@end
#import <objc/runtime.h>
static char const * const mydataKey = "mydata";
@implementation CCSprite (MyExtras)
@dynamic mydata;
- (id) mydata { return objc_getAssociatedObject(self, mydataKey); }
- (void) setMydata:(id)new { objc_setAssociatedObject(self, mydataKey, new, OBJC_ASSOCIATION_RETAIN_NONATOMIC); }
@end

That’s 10 lines.

2. Test it out.  Something like this:

CCSprite* buttonTest = [CCSprite spriteWithFile:@"buttontest.png"];
[buttonTest setMydata:[NSNumber numberWithInt:6]];   //use official setter method
buttonTest.mydata = [NSString stringWithFormat:@"hello"];  //ok too
CCLOG(@"buttonTest:%@",buttonTest.mydata);

All this does is attach an object to your sprite button, and spit it back out into the console log.  It’s flexible… attach any object you want this way, pretty much.  The second line makes it a NSNumber object, and the 3rd line replaces that with a NSString.  The only restriction here is you have to give .mydata an ID… that means you can’t say:

[buttonTest setMydata:6];

Because 6 is an int, not an id.  Get around that by using NSNumber.

If you want to read more, there’s lots of blog posts out there about this topic (try “associative references” in Objective C), and how to add other methods to extend existing classes, etc.  But this is just one common use case, simplified to its essentials.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>