From 0ce115bc9c44199ce52510e445ebce030d92431d Mon Sep 17 00:00:00 2001 From: Brian Donovan Date: Mon, 4 Oct 2010 15:18:54 -0700 Subject: [PATCH] Ensure observeValueForKeyPath:ofObject:change:context is called consistently. During the "normal" callback for new and old values, the ofObject: parameter passed to the observer is the original receiver of the addObserver:forKeyPath:options:context: call, but that isn't the case with the call caused by the CPKeyValueObservingOptionInitial option. This commit uses _targetObject, the receiver of the addObserver:... call, rather than self, the _CPKVOProxy. --- Foundation/CPKeyValueObserving.j | 2 +- Tests/AppKit/CPKeyValueObservingTest.j | 62 ++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 Tests/AppKit/CPKeyValueObservingTest.j diff --git a/Foundation/CPKeyValueObserving.j b/Foundation/CPKeyValueObserving.j index a08100481..c457baba5 100644 --- a/Foundation/CPKeyValueObserving.j +++ b/Foundation/CPKeyValueObserving.j @@ -360,7 +360,7 @@ var kvoNewAndOld = CPKeyValueObservingOptionNew|CPKeyValueObservingOptionOld, newValue = [CPNull null]; var changes = [CPDictionary dictionaryWithObject:newValue forKey:CPKeyValueChangeNewKey]; - [anObserver observeValueForKeyPath:aPath ofObject:self change:changes context:aContext]; + [anObserver observeValueForKeyPath:aPath ofObject:_targetObject change:changes context:aContext]; } } diff --git a/Tests/AppKit/CPKeyValueObservingTest.j b/Tests/AppKit/CPKeyValueObservingTest.j new file mode 100644 index 000000000..593bd01e0 --- /dev/null +++ b/Tests/AppKit/CPKeyValueObservingTest.j @@ -0,0 +1,62 @@ +@import + +@implementation CPKeyValueObservingTest : OJTestCase +{ + CPString _lastKeyPath; + id _lastObject; + CPDictionary _lastChange; + id _lastContext; +} + +- (void)setup +{ + _lastKeyPath = _lastObject = _lastChange = _lastContext = nil; +} + +- (void)testInitialObserving +{ + var tester = [ObservingTester testerWithCheese:@"CHEESE!"]; + [tester addObserver:self forKeyPath:@"cheese" options:CPKeyValueObservingOptionNew | CPKeyValueObservingOptionInitial context:nil]; + + [self assert:@"cheese" equals:_lastKeyPath]; + [self assert:tester equals:_lastObject]; + [self assert:[CPDictionary dictionaryWithObject:@"CHEESE!" forKey:CPKeyValueChangeNewKey] equals:_lastChange]; + [self assert:nil equals:_lastContext]; +} + +- (void)observeValueForKeyPath:(CPString)aKeyPath + ofObject:(id)anObject + change:(CPDictionary)aChange + context:(id)aContext +{ + _lastKeyPath = aKeyPath; + _lastObject = anObject; + _lastChange = aChange; + _lastContext = aContext; +} + +@end + +@implementation ObservingTester : CPObject +{ + id cheese; +} + ++ (id)testerWithCheese:(id)aCheese +{ + var tester = [[self alloc] init]; + [tester setCheese:aCheese]; + return tester; +} + +- (void)setCheese:(id)aCheese +{ + cheese = aCheese; +} + +- (id)cheese +{ + return cheese; +} + +@end \ No newline at end of file