Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using objc_setAssociatedObject with weak references

Tags:

I know that OBJC_ASSOCIATION_ASSIGN exists, but does it zero the reference if the target object is dealloced? Or is it like the old days where that reference needs to get nil-ed or we risk a bad access later on?

like image 972
ultramiraculous Avatar asked May 15 '13 16:05

ultramiraculous


2 Answers

As ultramiraculous demonstrated, OBJC_ASSOCIATION_ASSIGN does not do zeroing weak reference and you risk to access a deallocated object. But it’s quite easy to implement yourself. You just need a simple class to wrap an object with a weak reference:

@interface WeakObjectContainer : NSObject @property (nonatomic, readonly, weak) id object; @end  @implementation WeakObjectContainer - (instancetype) initWithObject:(id)object {     if (!(self = [super init]))         return nil;      _object = object;      return self; } @end 

Then you must associate the WeakObjectContainer as OBJC_ASSOCIATION_RETAIN(_NONATOMIC):

objc_setAssociatedObject(self, &MyKey, [[WeakObjectContainer alloc] initWithObject:object], OBJC_ASSOCIATION_RETAIN_NONATOMIC); 

and use the object property to access it in order to get a zeroing weak reference:

id object = [objc_getAssociatedObject(self, &MyKey) object]; 
like image 145
0xced Avatar answered Sep 19 '22 13:09

0xced


One more option similar to WeakObjectContainer:

- (id)weakObject {     id (^block)(void) = objc_getAssociatedObject(self, @selector(weakObject));     return (block ? block() : nil); }  - (void)setWeakObject:(id)object {     id __weak weakObject = object;     id (^block)(void) = ^{ return weakObject; };     objc_setAssociatedObject(self, @selector(weakObject),                              block, OBJC_ASSOCIATION_COPY); } 
like image 21
Vadim Avatar answered Sep 17 '22 13:09

Vadim