In Cocoa devo rimuovere un oggetto dalla ricezione delle notifiche KVO durante la deallocazione?

StackOverflow https://stackoverflow.com/questions/13927

  •  08-06-2019
  •  | 
  •  

Domanda

Quando ho registrato un oggetto pippo per ricevere notifiche KVO da un altro oggetto sbarra (usando addObserver:...), se poi dealloco pippo devo inviare un removeObserver:forKeyPath: messaggio a sbarra in -dealloc?

È stato utile?

Soluzione

Devi usare -removeObserver: forKeyPath: per rimuovere l'osservatore prima che - [NSObject dealloc] venga eseguito, quindi sì, facendolo nel -dealloc Il metodo della tua classe funzionerebbe.

Meglio di così, però, sarebbe avere un punto deterministico in cui qualunque cosa possieda l'oggetto che sta facendo l'osservazione potrebbe dire che è stato fatto e (eventualmente) sarà deallocato. In questo modo, puoi interrompere immediatamente l'osservazione quando la cosa che fa l'osservazione non è più necessaria, indipendentemente da quando è effettivamente deallocata.

Questo è importante da tenere a mente perché la durata degli oggetti in Cocoa non è così deterministica come alcune persone sembrano pensare che lo sia. I vari framework Mac OS X stessi invieranno i tuoi oggetti -retain e -autorelease , estendendo la loro durata oltre ciò che altrimenti potresti pensare che sarebbe .

Inoltre, quando si passa alla garbage collection di Objective-C, si troverà che -finalize verrà eseguito in tempi molto diversi - e in contesti molto diversi - rispetto a -dealloc . Per prima cosa, la finalizzazione avviene su un thread diverso, quindi in realtà non puoi inviare in sicurezza -removeObserver: forKeyPath: a un altro oggetto in un -finalize metodo.

Gestisci la memoria (e altre risorse scarse) in -dealloc e -finalize e usa un metodo -invalidate separato per avere un proprietario dice a un oggetto che hai finito con esso in un punto deterministico; fare cose come rimuovere le osservazioni KVO lì. L'intento del tuo codice sarà più chiaro e avrai meno bug sottili di cui occuparti.

Altri suggerimenti

Un po 'di informazioni extra che ho acquisito da un'esperienza dolorosa: sebbene NSNotificationCenter utilizzi i riferimenti deboli a zero durante l'esecuzione in Garbage Collection, KVO no. Pertanto, puoi evitare di non rimuovere un osservatore NSNotificationCenter quando usi GC (quando usi la conservazione / rilascio, devi comunque rimuovere il tuo osservatore), ma devi comunque rimuovere i tuoi osservatori KVO, come descrive Chris.

Sicuramente d'accordo con Chris sulla gestione di "attenersi alla memoria (e altre risorse scarse) in -dealloc e -finalize ... " commento. Molte volte vedrò persone che provano a invalidare gli oggetti NSTimer nelle loro funzioni dealloc. Il problema è che NSTimer mantiene i suoi obiettivi. Quindi, se il target di quel NSTimer è self, dealloc non verrà mai chiamato provocando perdite di memoria potenzialmente cattive.

Invalida in -invalidate ed esegui un'altra pulizia della memoria nel tuo dealloc e finalize.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top