Skip to content

Commit

Permalink
Merge pull request #11 from lono175/upstream/master2
Browse files Browse the repository at this point in the history
Fix a crash when the given context points to a non-objc object
  • Loading branch information
Krzysztof Zabłocki committed Jan 28, 2013
2 parents 7f1b39a + da58bf7 commit 86ab83c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 11 deletions.
21 changes: 10 additions & 11 deletions SFObservers/NSObject+SFObservers.m
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

@interface __SFObserversKVOObserverInfo : NSObject
@property(nonatomic, copy) NSString *keyPath;
@property(nonatomic, AH_WEAK) id context;
@property(nonatomic, assign) void *context;
@property(nonatomic, assign) void *blockKey;
@end

Expand Down Expand Up @@ -70,7 +70,7 @@ - (void)setAllowMethodForwarding:(BOOL)allowForwarding
objc_setAssociatedObject(self, AH_BRIDGE(NSObjectKVOSFObserversAllowMethodForwardingKey), [NSNumber numberWithBool:allowForwarding], OBJC_ASSOCIATION_RETAIN);
}

- (void)sf_addObserver:(id)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(id)aContext
- (void)sf_addObserver:(id)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)aContext
{
//! store info into our observer structure
NSMutableDictionary *registeredKeyPaths = (NSMutableDictionary *)objc_getAssociatedObject(observer, AH_BRIDGE(NSObjectKVOSFObserversArrayKey));
Expand Down Expand Up @@ -117,17 +117,16 @@ - (void)sf_addObserver:(id)observer forKeyPath:(NSString *)keyPath options:(NSKe
//! Add auto remove when observer is going to be deallocated
__unsafe_unretained __block id weakSelf = self;
__unsafe_unretained __block id weakObserver = observer;
__unsafe_unretained __block id weakContext = aContext;

void *key = [observer performBlockOnDealloc:^{
int numberOfRemovals = 0;
if ((numberOfRemovals = [weakSelf sf_removeObserver:weakObserver forKeyPath:keyPath context:weakContext registeredKeyPaths:registeredKeyPaths])) {
if ((numberOfRemovals = [weakSelf sf_removeObserver:weakObserver forKeyPath:keyPath context:aContext registeredKeyPaths:registeredKeyPaths])) {
for (int i = 0; i < numberOfRemovals; ++i) {
[weakSelf setAllowMethodForwarding:YES];
#if SF_OBSERVERS_LOG_ORIGINAL_METHODS
NSLog(@"Calling original method %@ with parameters %@ %@ %@", NSObjectKVOSFObserversRemoveSpecificSelector, weakObserver, keyPath, weakContext);
NSLog(@"Calling original method %@ with parameters %@ %@ %p", NSObjectKVOSFObserversRemoveSpecificSelector, weakObserver, keyPath, aContext);
#endif
objc_msgSend(weakSelf, NSSelectorFromString(NSObjectKVOSFObserversRemoveSpecificSelector), weakObserver, keyPath, weakContext);
objc_msgSend(weakSelf, NSSelectorFromString(NSObjectKVOSFObserversRemoveSpecificSelector), weakObserver, keyPath, aContext);
[weakSelf setAllowMethodForwarding:NO];
}
}
Expand All @@ -137,7 +136,7 @@ - (void)sf_addObserver:(id)observer forKeyPath:(NSString *)keyPath options:(NSKe

//! call originalMethod
#if SF_OBSERVERS_LOG_ORIGINAL_METHODS
NSLog(@"Calling original method %@ with parameters %@ %@ %d %@", NSObjectKVOSFObserversAddSelector, observer, keyPath, options, aContext);
NSLog(@"Calling original method %@ with parameters %@ %@ %d %p", NSObjectKVOSFObserversAddSelector, observer, keyPath, options, aContext);
#endif
objc_msgSend(self, NSSelectorFromString(NSObjectKVOSFObserversAddSelector), observer, keyPath, options, aContext);
}
Expand Down Expand Up @@ -167,11 +166,11 @@ - (void)sf_removeObserver:(id)observer forKeyPath:(NSString *)keyPath
}
}

- (void)sf_removeObserver:(id)observer forKeyPath:(NSString *)keyPath context:(id)context
- (void)sf_removeObserver:(id)observer forKeyPath:(NSString *)keyPath context:(void *)context
{
if ([self allowMethodForwarding]) {
#if SF_OBSERVERS_LOG_ORIGINAL_METHODS
NSLog(@"Calling original method %@ with parameters %@ %@ %@", NSObjectKVOSFObserversRemoveSpecificSelector, observer, keyPath, context);
NSLog(@"Calling original method %@ with parameters %@ %@ %p", NSObjectKVOSFObserversRemoveSpecificSelector, observer, keyPath, context);
#endif
objc_msgSend(self, NSSelectorFromString(NSObjectKVOSFObserversRemoveSpecificSelector), observer, keyPath, context);
return;
Expand All @@ -182,7 +181,7 @@ - (void)sf_removeObserver:(id)observer forKeyPath:(NSString *)keyPath context:(i
if ([self allowMethodForwarding] || (numberOfRemovals = [self sf_removeObserver:observer forKeyPath:keyPath context:context registeredKeyPaths:registeredKeyPaths])) {
for (int i = 0; i < numberOfRemovals; ++i) {
#if SF_OBSERVERS_LOG_ORIGINAL_METHODS
NSLog(@"Calling original method %@ with parameters %@ %@ %@", NSObjectKVOSFObserversRemoveSpecificSelector, observer, keyPath, context);
NSLog(@"Calling original method %@ with parameters %@ %@ %p", NSObjectKVOSFObserversRemoveSpecificSelector, observer, keyPath, context);
#endif
[self setAllowMethodForwarding:YES];
objc_msgSend(self, NSSelectorFromString(NSObjectKVOSFObserversRemoveSpecificSelector), observer, keyPath, context);
Expand All @@ -194,7 +193,7 @@ - (void)sf_removeObserver:(id)observer forKeyPath:(NSString *)keyPath context:(i

- (NSUInteger)sf_removeObserver:(id)observer
forKeyPath:(NSString *)keyPath
context:(id)context
context:(void *)context
registeredKeyPaths:(NSMutableDictionary *)registeredKeyPaths
{
__block NSUInteger result = 0;
Expand Down
8 changes: 8 additions & 0 deletions Sample Project/Sample ProjectTests/Sample_ProjectTests.m
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,14 @@ - (void)testKVOAutoRemovalWithContext
AH_RELEASE(observedObject), observedObject = nil;
}

- (void)testKVOAutoRemovalWithIntegerContext
{
static NSInteger SomeIntegerContext;
[observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:&SomeIntegerContext];
AH_RELEASE(observer), observer = nil;
AH_RELEASE(observedObject), observedObject = nil;
}

- (void)testKVOAutoRemovalMultiple
{
[observedObject addObserver:observer forKeyPath:@"description" options:NSKeyValueObservingOptionNew context:AH_BRIDGE(self)];
Expand Down

0 comments on commit 86ab83c

Please sign in to comment.