How to determine which NSNotification is crashing due to dealloc-ed observer
Asked Answered
H

2

10

The golden rule of using NSNotification seems to be

"call removeObserver before the observer (or the object) is deallocated".

I'm dealing with a codebase where this rule hasn't been followed, but I can't locate the transgression. I've searched through the code and ensured that every addObserver has a matching removeObserver but I'm still seeing crash reports of the following variety:

OS Version:      iPhone OS 5.0.1 (9A405)
Report Version:  104

Exception Type:  SIGSEGV
Exception Codes: SEGV_ACCERR at 0x8
Crashed Thread:  0

Thread 0 Crashed:
0   libobjc.A.dylib                     0x31516fbc objc_msgSend + 16
1   Foundation                          0x3195b50f __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 19
2   CoreFoundation                      0x37a02577 ___CFXNotificationPost_block_invoke_0 + 71
3   CoreFoundation                      0x3798e0cf _CFXNotificationPost + 1407
4   Foundation                          0x318cf3fb -[NSNotificationCenter postNotificationName:object:userInfo:] + 67
5   UIKit                               0x34e5ee25 -[UIApplication _handleApplicationSuspend:eventInfo:] + 697
6   UIKit                               0x34deed17 -[UIApplication handleEvent:withNewEvent:] + 2031
7   UIKit                               0x34dee3bf -[UIApplication sendEvent:] + 55
8   UIKit                               0x34dedd2d _UIApplicationHandleEvent + 5809
9   GraphicsServices                    0x3750bdf3 PurpleEventCallback + 883
10  CoreFoundation                      0x37a0a553 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 39
11  CoreFoundation                      0x37a0a4f5 __CFRunLoopDoSource1 + 141
12  CoreFoundation                      0x37a09343 __CFRunLoopRun + 1371
13  CoreFoundation                      0x3798c4dd CFRunLoopRunSpecific + 301
14  CoreFoundation                      0x3798c3a5 CFRunLoopRunInMode + 105
15  GraphicsServices                    0x3750afcd GSEventRunModal + 157
16  UIKit                               0x34e1c743 UIApplicationMain + 1091
17  App                                 0x00002d2f main (main.m:14)

My interpretation of this crash report is that [UIApplication _handleApplicationSuspend:eventInfo:] is posting a notification for which an observer has been deallocated before being removed.

Assuming this interpretations is correct, how would I go about determining which notification is being posted? And ideally, what the deallocated object type?

Hereabouts answered 19/2, 2012 at 8:31 Comment(0)
F
6

You can set a symbolic breakpoint in -[NSNotificationCenter postNotificationName:object:userInfo:] and print the third argument passed to it (the first being the NSNotificationCenter, the second, _cmd) using the debugger po command.

Faustofaustus answered 19/2, 2012 at 11:58 Comment(3)
great idea. I was approaching it from the 'intercepting postNotification at runtime' angle, but during debug is a fine alternative (and answers the actual question).Hereabouts
Just to add a little more detail, I added a symbolic breakpoint in [NSNotificationCenter postNotificationName:object:userInfo:] as suggested and set the "action" of the breakpoint to a "debugger command" of "po $r2". When running the app on device and suspending it I see many notifications posted during [UIApplication _handleApplicationSuspend:eventInfo:] but the only notifications matching the crash report call stack are UIApplicationSuspendedNotification and UIApplicationDidEnterBackgroundNotification (predictably)Hereabouts
Wonderful answer. I feel like I was blind before. If you use "po $rdi" as the "debugger command" on Mac, you can see the Notification name.Hiedihiemal
R
0

Another way to determine this is to get the name parameter value (the string you passed for posting the notification) and verify that any object that is observing that string/name is set to remove observation sometime in the objects lifecycle or as it is deallocating.

Rafiq answered 26/3, 2013 at 19:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.