So I have a MainController,
inside of the header I have this void*
declared:
static void *kStrokeColorWellChangedContext = &kStrokeColorWellChangedContext;
Inside of the implementation I am handling observation:
-(void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object
change:(NSDictionary *)change
context:(void*)context
{
if( [keyPath isEqualToString:@"color"] )
{
if( context == kStrokeColorWellChangedContext )
{
[self setValue:[change objectForKey:@"new"] forKey:@"strokeColor"];
}
}
Then I have a ViewController which has this line, which adds the MainController as an observer to a view
[self.strokeColorWell addObserver:self.toolController forKeyPath:@"color" options:NSKeyValueObservingOptionNew context:kStrokeColorWellChangedContext];
So when the view's color changes, it notifies the MainController, and enters the -observeValueForKey:
routine, w/ the key @"color"
But it fails to enter into the inner if
block, where I am checking context
.
If I were to swap out my void*
with an NSString*
instead, it works as I would expect.
How could it be possible that the void*
appears to have two different addresses stored into it?
EDIT:
Maybe the values of the void*
could help
the result of po kStrokeColorWellChangedContext
:
0x00000001005553e8
the result of po context
in -observeValueForKey:
:
0x0000000100555ea0
objc[17775]: Method cache corrupted. This may be a message to an invalid object, or a memory error somewhere else.
objc[17775]: receiver 0x100555ea0, SEL 0x7fff899c8246, isa 0x100555ea0, cache > 0x100555eb0, buckets 0x100566160, mask 0x0, occupied 0x0
objc[17775]: receiver 0 bytes, buckets 0 bytes
objc[17775]: selector 'respondsToSelector:'
The exceptions being thrown there may be a hint, but I really don't understand any of it
EDIT2:
The output of p
instead of po
(lldb) p context
(void *) $5 = 0x0000000100555ea0
(lldb) p kStrokeColorWellChangedContext
(void *) $6 = 0x00000001005553e8
Please note that I am pretty-very confident that I am debugging the correct notification.
Two reasons why; the keyPath
is unique and I see that value is correct. Also if I use an NSString*
as the context it works
The problem is that you're defining kStrokeColorWellChangedContext
as a static
variable in a header. Each translation unit (source file, basically) that imports that header will create a separate variable by that name, because it's declared static
and that's what that means for variables at file scope.
So, each variable will have a separate address and, since the variable's value is its own address, each will have a different value.
You could declare the variable in the header and define it in an implementation such that there's only one such variable. The declaration in the header would look like:
extern void * const kStrokeColorWellChangedContext;
The definition in one of the implementation files would look like:
void * const kStrokeColorWellChangedContext = (void*)&kStrokeColorWellChangedContext;
Note that I've made the variable a const
pointer to void. That disallows anything from assigning a new value to it, since it's supposed to be a constant.
This works for me - kStrokeColorWellChangedContext
"has" two addresses: its position in memory and its value and they're both the same! So kStrokeColorWellChangedContext
and & kStrokeColorWellChangedContext
should be interchangeable throughout your program.
Have you tried stepping through your KVO callback and looking at/logging the values of context
and kStrokeColorWellChangedContext
? And keyPath
?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With