• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: Sensible way to extend base class?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Sensible way to extend base class?


  • Subject: Re: Sensible way to extend base class?
  • From: Louis Gerbarg <email@hidden>
  • Date: Thu, 21 May 2009 07:09:10 -0400

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 (email@hidden)

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:

This email sent to email@hidden

References: 
 >Sensible way to extend base class? (From: Graham Cox <email@hidden>)
 >Re: Sensible way to extend base class? (From: Ken Thomases <email@hidden>)
 >Re: Sensible way to extend base class? (From: Greg Parker <email@hidden>)
 >Re: Sensible way to extend base class? (From: Michael Ash <email@hidden>)
 >Re: Sensible way to extend base class? (From: Greg Parker <email@hidden>)
 >Re: Sensible way to extend base class? (From: Michael Ash <email@hidden>)

  • Prev by Date: problems with inspector window
  • Next by Date: Re: NSTextView - Having to call setFrame twice to work?
  • Previous by thread: Re: Sensible way to extend base class?
  • Next by thread: Re: Sensible way to extend base class?
  • Index(es):
    • Date
    • Thread