How do I use objc_setAssociatedObject/objc_getAssociatedObject inside an object?
If I use objc_setAssociatedObject/objc_getAssociatedObject inside a category implementation to store a simulated instance variable in a setter method, how would I access the key in the getter method since any variables declared in the setter method would be outside the scope of the getter method?
Edit: To clarify, if I were to use the following pattern, where should I declare STRING_KEY so that I could use it in both the setter and the getter method.
@interface NSView (simulateVar)
-(void)setSimualtedString:(NSString *)myString;
-(NSString *)simulatedString;
@end
@implementation NSView (simulateVar)
-(void)setSimualtedString: (NSString *)myString
{
objc_setAssociatedObject(self, &STRING_KEY, myString, OBJC_ASSOCIATION_RETAIN);
}
-(NSString *)simulatedString
{
return (NSString *)objc_getAssociatedObject(self, &STRING_KEY);
}
@end
Declare a static variable so that you can use its address as the key. The call to objc_setAssociatedObject takes a void* and only the address of your static variable is actually used, not the contents of a NSString... that is only wasting memory.
You just need to add:
static char STRING_KEY; // global 0 initialization is fine here, no
// need to change it since the value of the
// variable is not used, just the address
I know that this question is quit old but I think for completeness there is another way how to use associated objects worth mentioning. This solution utilizes @selector
and therefore there is no need for any extra variable or constant.
@interface NSObject (CategoryWithProperty)
@property (nonatomic, strong) NSObject *property;
@end
@implementation NSObject (CategoryWithProperty)
- (NSObject *)property {
return objc_getAssociatedObject(self, @selector(property));
}
- (void)setProperty:(NSObject *)value {
objc_setAssociatedObject(self, @selector(property), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
(inspired by http://www.tuaw.com/2013/04/10/devjuice-better-objective-c-associated-objects/)
For associated storage void *
keys, I like this way of doing it:
static void * const kMyAssociatedStorageKey = (void*)&kMyAssociatedStorageKey;
This avoids having another constant string in the executable, and by setting its value to the address of itself, you get good uniquing, and const
behavior (so you'll nominally get a compiler complaint if you do something that would change the value of the key), without any extra unnecessary exported symbols.
Declare a static (compilation unit-scope) variable at the top level of the source file. It may help to make it meaningful, something like this:
static NSString *MYSimulatedString = @"MYSimulatedString";