Skip to content

Commit

Permalink
actually use objc_(load/store)Weak to ensure that a listener is nev…
Browse files Browse the repository at this point in the history
…er called on a over released target
  • Loading branch information
racarone committed Feb 1, 2016
1 parent 05e6b6c commit 27f1c0c
Showing 1 changed file with 20 additions and 11 deletions.
31 changes: 20 additions & 11 deletions sparrow/src/Classes/SPEventListener.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,46 @@
#import "SPNSExtensions.h"

#import <objc/message.h>
#import <objc/runtime.h> // weak

@implementation SPEventListener
{
id _target;
SPEventBlock _block;
id __weak _target;
SEL _selector;
}

static inline id getTarget(SPEventListener *self)
{
return objc_loadWeak(&self->_target);
}

#pragma mark Initialization

- (instancetype)initWithTarget:(id)target selector:(SEL)selector block:(SPEventBlock)block
{
if (self = [super init])
{
objc_storeWeak(&_target, target);
_block = [block copy];
_target = target;
_selector = selector;
}

return self;
}

- (void)dealloc
{
[_block release];
[super dealloc];
}

- (instancetype)initWithTarget:(id)target selector:(SEL)selector
{
__block id weakTarget = target;

return [self initWithTarget:target selector:selector block:^(SPEvent *event)
{
typedef void (*EventFunc)(id, SEL, SPEvent *);
((EventFunc)objc_msgSend)(weakTarget, selector, event);
((EventFunc)objc_msgSend)(getTarget(self), selector, event);
}];
}

Expand All @@ -52,12 +62,6 @@ - (instancetype)initWithBlock:(SPEventBlock)block
return [self initWithTarget:nil selector:nil block:block];
}

- (void)dealloc
{
[_block release];
[super dealloc];
}

#pragma mark Methods

- (void)invokeWithEvent:(SPEvent *)event
Expand All @@ -72,4 +76,9 @@ - (BOOL)fitsTarget:(id)target andSelector:(SEL)selector orBlock:(SPEventBlock)bl
return fitsTargetAndSelector || fitsBlock;
}

- (id)target
{
return getTarget(self);
}

@end

0 comments on commit 27f1c0c

Please sign in to comment.