Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Evil KVO context hack using macros + C99 compound literal syntax.
// Building upon: http://www.dribin.org/dave/blog/archives/2008/09/24/proper_kvo_usage/
// Defines a unique KVO context by taking the address of a 2-element string array.
// Using __FILE__ ensures the address is unique across source files, even with link time optimization.
#define DDDefineContext(_X_) static void * _X_ = &(const char *[] ) {#_X_, __FILE__}
// Example Definition
DDDefineContext(MyFooContext);
// Example Usage. No need for &MyFooContext to make it unique.
- (void)startObserving
{
[_ivar addObserver:self forKeyPath:@"foo" options:0 context:MyFooContext];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// In a debugger, use `p *(char **)context` to dump the context
if (context == MyFooContext) {
// foo changed
} else {
[super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
}
}
- (void)stopObserving
{
[_ivar removeObserver:self forKeyPath:@"foo" context:MyFooContext];
}
@kylesluder

This comment has been minimized.

Copy link

kylesluder commented Mar 14, 2013

I feel like I should point you at @mikeash's incredibly clever use of C:

static const void *MyFooContext = &MyFooContext;

MyFooContext is initialized at load time with a pointer to itself.

@ddribin

This comment has been minimized.

Copy link
Owner Author

ddribin commented Mar 14, 2013

Yeah, but I really like being able to print out the context in OVFKP while debugging and get something useful.

@0xced

This comment has been minimized.

Copy link

0xced commented Mar 14, 2013

It looks like you missed a mention ;-)

@ddribin Re http://www.dribin.org/dave/blog/archives/2008/09/24/proper_kvo_usage/ You can correlate the context address with a particular context variable: (gdb) info symbol context

Or with lldb (given that you defined MyFooContext as Kyle described):

(lldb) image lookup -a `context`
      Address: MyApp[0x00026258] (MyApp.__DATA.__data + 4)
      Summary: MyFooContext
@ddribin

This comment has been minimized.

Copy link
Owner Author

ddribin commented Mar 14, 2013

Oh… nice! Yeah, I didn’t know about the syntax. That does work well. Less hacky, too. Thanks!

@kylesluder

This comment has been minimized.

Copy link

kylesluder commented Mar 14, 2013

Because gist comment markdown sucks, I didn't realize you folks were referring to the shell-like backtick syntax. I was worried vararg macros were somehow involved…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.