10

La regola d'oro di utilizzare NSNotification sembra esserecome determinare quale NSNotification si blocca a causa di dealloc-ed osservatore

"chiamano removeObserver prima del observer (o la object) viene deallocato".

Ho a che fare con un codebase in cui questa regola non è stata seguita, ma non riesco a localizzare la trasgressione. Ho cercato attraverso il codice e ha assicurato che ogni addObserver ha un corrispondente removeObserver ma sto ancora vedendo segnalazioni di crash delle seguenti varietà:

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) 

La mia interpretazione di questa relazione incidente è che [UIApplication _handleApplicationSuspend:eventInfo:] sta inviando una notifica per che un osservatore è stato deallocato prima di essere rimosso.

Supponendo che queste interpretazioni siano corrette, come procedere per determinare quale notifica viene inviata? E idealmente, quale è il tipo di oggetto deallocato?

risposta

6

è possibile impostare un punto di interruzione simbolica in -[NSNotificationCenter postNotificationName:object:userInfo:] e stampare il terzo argomento passato ad esso (il primo è il NSNotificationCenter, il secondo, _cmd) utilizzando il po comando del debugger.

+0

ottima idea. Lo stavo avvicinando dall'angolo "intercettazione postNotification at runtime", ma durante il debug è un'alternativa valida (e risponde alla domanda reale). –

+3

Per aggiungere un po 'più di dettaglio, ho aggiunto un punto di interruzione simbolico in '[NSNotificationCenter postNotificationName: object: userInfo:]' come suggerito e impostare "l'azione" del breakpoint su un "comando debugger" di "po $ r2". Quando si esegue l'applicazione sul dispositivo e la si sospende vedo molte notifiche pubblicate durante '[UIApplication _handleApplicationSuspend: eventInfo:]' ma le uniche notifiche che corrispondono allo stack delle chiamate ai crash report sono 'UIApplicationSuspendedNotification' e' UIApplicationDidEnterBackgroundNotification' (prevedibilmente) –

+0

Risposta meravigliosa. Mi sento come se fossi cieco prima. Se si utilizza "po $ rdi" come "comando debugger" su Mac, è possibile vedere il nome della notifica. – Charlesism

0

Un altro modo per determinare ciò è ottenere il valore del parametro nome (la stringa passata per la pubblicazione della notifica) e verificare che qualsiasi oggetto che sta osservando quella stringa/nome sia impostato per rimuovere l'osservazione nel ciclo di vita degli oggetti o come è deallocare.