As several people have mentioned, doing this kind of thing is very skanky, and it won't work properly under GC without some additional machinery. But if GC is not a concern you can do something that works with a bit grotesque monkey patching. The below code is generic, but it mucks with everything. I recommend you always trim it down from NSObject to whatever class you are actually doing it to.
Louis #import <pthread.h> #import <Foundation/Foundation.h> @interface NSObject (LGAssociativeStorage) @property (retain) id associatedObject; @end ----------------------------------------------------------- #import <objc/runtime.h> #import "LGAssociativeStorage.h" /* We are using STL containers because: 1) Using Objective C containers can cause deallocs which cause recursion issues 2) STL containers are high perf containers that don't introduce external code dependencies Ideally one could include a thread safe map implementation, but I don't need one currently */ #include <map> typedef std::map<id, __strong id> idMap_t; typedef std::pair<id, __strong id> idPair_t; static NSMutableDictionary * data = nil; static pthread_mutex_t data_lock = PTHREAD_MUTEX_INITIALIZER; static IMP gOriginalNSObjectDealloc = nil; static idMap_t associatedObjectMap; static void removeAssociatedObjectFromMap(id self) { idMap_t::iterator iter = associatedObjectMap.find(self); if( iter != associatedObjectMap.end() ) { [iter->second release]; associatedObjectMap.erase(iter); } } static id newNSObjectDealloc(id self, SEL deallocSelector, ...) { pthread_mutex_lock(&data_lock); removeAssociatedObjectFromMap(self); pthread_mutex_unlock(&data_lock); return gOriginalNSObjectDealloc(self, deallocSelector); } static void initIfNecessary(void) { if (!data) { data = [[NSMutableDictionary alloc] init]; // The below line of code is abusive... in the future the Objective C runtime will use it as evidence // that I am an unfit software engineer and take custody of all my code gOriginalNSObjectDealloc = class_replaceMethod([NSObject class], @selector( dealloc), newNSObjectDealloc, "v@:"); } } @implementation NSObject (LGAssociativeStorage) - (id) associatedObject { id retval = nil; pthread_mutex_lock(&data_lock); initIfNecessary(); idMap_t::iterator iter = associatedObjectMap.find(self); if( iter != associatedObjectMap.end() ) { retval = iter->second; } pthread_mutex_unlock(&data_lock); return retval; } - (void) setAssociatedObject:(id)object_ { pthread_mutex_lock(&data_lock); initIfNecessary(); removeAssociatedObjectFromMap(self); [object_ retain]; associatedObjectMap.insert(idPair_t(self, object_)); pthread_mutex_unlock(&data_lock); } @end _______________________________________________ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com