10

Złota zasada korzystania NSNotification wydaje się byćJak określić, która NSNotification jest upaść z powodu dealloc-ed obserwator

„call removeObserver przed observer (lub object) jest zwalniane”.

Mam do czynienia z podstawą kodu, w której ta reguła nie była przestrzegana, ale nie mogę zlokalizować tego wykroczenia. Rozglądałem się za pomocą kodu i zapewnić, że każdy addObserver ma dopasowanie removeObserver ale nadal widzę raportów o awariach następującej odmiany:

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) 

Moja interpretacja tego raportu jest to, że katastrofy [UIApplication _handleApplicationSuspend:eventInfo:] publikuje zawiadomienie o którego obserwator został zwolniony przed usunięciem.

Zakładając, że interpretacje te są poprawne, , w jaki sposób mogę ustalić, które powiadomienie jest wysyłane? A najlepiej, jaki jest typ dealokowanych obiektów?

Odpowiedz

6

Można ustawić symboliczny przerwania w -[NSNotificationCenter postNotificationName:object:userInfo:] i wydrukować trzeci argument przekazany do niego (pierwszy będąc NSNotificationCenter, drugi, _cmd) stosując po komendy debuggera.

+0

świetny pomysł. Podchodziłem do tego z punktu "przechwytywanie postNotification at runtime", ale podczas debugowania jest dobra alternatywa (i odpowiada na faktyczne pytanie). –

+3

Aby dodać trochę więcej szczegółów, dodałem symboliczny punkt przerwania w '[NSNotificationCenter postNotificationName: object: userInfo:]' zgodnie z sugestią i ustaw "akcję" punktu przerwania na "polecenie debuggera" w "po $ r2". Podczas uruchamiania aplikacji na urządzeniu i zawieszania go widzę wiele powiadomień opublikowanych podczas "[UIApplication _handleApplicationSuspend: eventInfo:]", ale jedynymi powiadomieniami pasującymi do stosu wywołań raportów awarii są "UIApplicationSuspendedNotification" i "UIApplicationDidEnterBackgroundNotification" (przewidywalnie). –

+0

Cudowna odpowiedź. Czuję, że wcześniej byłam ślepa. Jeśli użyjesz "po $ rdi" jako "polecenia debuggera" na Macu, zobaczysz nazwę Powiadomienia. – Charlesism

0

Innym sposobem określenia tego jest uzyskanie wartości parametru nazwy (napisu, który przekazałeś do wysłania powiadomienia) i sprawdzenie, czy dowolny obiekt obserwujący ten ciąg/nazwa jest ustawiony tak, aby usunąć obserwację w czasie cyklu życia obiektów lub jako to jest zwolnienie.

Powiązane problemy