views:

153

answers:

1

For some better understanding on what happens “under the hood”, I would love to do a complete trace of any notifications happening within my application.

Naïve as I am, the first thing I tried was registering like this:

Somewhere in my app:

{
    [...]
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(traceNotifications:) name:nil object:nil];
    [...]
}

- (void)traceNotifications:(NSNotification *)notification
{
    NSLog(@"received notification %@", [notification name]);
}

I do actually get a number of notifications that way. But at some point the application does crash. The stack trace shows it is crashing with EXC_BAD_ACCESS in realizeClass, which from my experience does indicate that something gets called after its deallocation. My observing object however still is alive, its deallocator has not been called (yet).

Next thing I tried was setting a breakpoint towards -[NSNotificationCenter postNotification:] and then run po {NSNotification *}($ebp+16) inside the gdb-console whenever my breakpoint is trapped. That did reveal a few notifications but not all that I am expecting/hoping for. For example, my application does handle orientation-changes properly but I do not see any notifications being trapped when reorienting the device (in the simulator).

What am I missing? Is there a way (e.g. a tool) for reliably observing a NSNotificationCenter?

Thanks for any hint.

+1  A: 

The only solution I got to work was using breakpoints.

I added a breakpoint at __CFXNotificationPost_old (CoreFoundation) and bundled that with a Debugger Command po {NSNotification *}($ebp+12). All of this is nicely doable within the Xcode GUI:

  • click on "Run" on the Xcode application menu (top of the screen)
  • select "Debugger"
  • within the Debugger window click on "Show-Breakpoints"
  • click on the "Enter Symbol-Name"-line and enter "__CFXNotificationPost_old"
  • click on the "+" on the very right side
  • select "Debugger Command" on that dropdown-list
  • enter "po {NSNotification *}($ebp+12)
  • (you may also want to activate logging by checking the "Log" checkbox at the bottom)
  • run your app in a simulator-debug-session from within Xcode

The app will stop its execution whenever a NSNotification is posted and display it within the gdb-console.

I did try to create a tracepoint within gdb but failed because the tracepoint actions within Xcode gdb seem to buggy - or maybe I am just too stoopid to get them working.

I also tried to create a custom Instruments Dtrace script, but failed as my Dtrace Karate just isnt strong enough.

If you manage to get any of the latter options to work, please go ahead and post them as an alternative answer - I will upvote and mark them as the favored one.

Till