diff --git a/Foundation/CPKeyValueObserving.j b/Foundation/CPKeyValueObserving.j index a3ef96b07..6db7a6405 100644 --- a/Foundation/CPKeyValueObserving.j +++ b/Foundation/CPKeyValueObserving.j @@ -295,6 +295,8 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew | CPKeyValueObservingOpti if ([_replacedKeys containsObject:aKey] || ![_nativeClass automaticallyNotifiesObserversForKey:aKey]) return; + [_replacedKeys addObject:aKey]; + var theClass = _nativeClass, KVOClass = _targetObject.isa, capitalizedKey = aKey.charAt(0).toUpperCase() + aKey.substring(1); diff --git a/Tests/Foundation/CPKVOTest.j b/Tests/Foundation/CPKVOTest.j index 49bc9f617..55cde1709 100644 --- a/Tests/Foundation/CPKVOTest.j +++ b/Tests/Foundation/CPKVOTest.j @@ -440,6 +440,30 @@ [self assert:observationCount equals:3]; } +- (void)testSettersReplacedOnce +{ + var bob = [[PersonTester alloc] init], + betty = [CPObject new]; + + [bob addObserver:self forKeyPath:@"name" options:nil context:"testSettersReplacedOnce"]; + + var oldImp = class_getMethodImplementation(bob.isa, @selector(setName:)); + + [bob removeObserver:self forKeyPath:@"name"]; + + [bob addObserver:self forKeyPath:@"name" options:nil context:"testSettersReplacedOnce"]; + + var newImp = class_getMethodImplementation(bob.isa, @selector(setName:)); + + [self assertTrue:newImp === oldImp]; + + [bob addObserver:betty forKeyPath:@"name" options:nil context:"testSettersReplacedOnce"]; + + var newImp = class_getMethodImplementation(bob.isa, @selector(setName:)); + + [self assertTrue:newImp === oldImp]; +} + - (void)observeValueForKeyPath:(CPString)aKeyPath ofObject:(id)anObject change:(CPDictionary)changes context:(id)aContext { var oldValue = [changes objectForKey:CPKeyValueChangeOldKey],