Muss ich in Cocoa ein Objekt vom Empfang von KVO-Benachrichtigungen entfernen, wenn ich die Zuordnung aufhebe?

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

  •  08-06-2019
  •  | 
  •  

Frage

Wenn ich ein Objekt registriert habe foo um KVO-Benachrichtigungen von einem anderen Objekt zu erhalten Bar (mit addObserver:...), wenn ich dann die Zuordnung aufhebe foo Muss ich eine schicken? removeObserver:forKeyPath: Nachricht an Bar in -dealloc?

War es hilfreich?

Lösung

Sie müssen verwenden -removeObserver:forKeyPath: den Beobachter vorher entfernen -[NSObject dealloc] läuft, also ja, ich mache es in der -dealloc Methode Ihrer Klasse würde funktionieren.

Besser wäre es jedoch, einen deterministischen Punkt zu haben, an dem der Eigentümer des Objekts, das die Beobachtung durchführt, ihm mitteilen könnte, dass es erledigt ist und (irgendwann) freigegeben wird.Auf diese Weise können Sie die Beobachtung sofort beenden, wenn das Objekt, das die Beobachtung durchführt, nicht mehr benötigt wird, unabhängig davon, wann die Zuordnung tatsächlich aufgehoben wird.

Dies ist wichtig zu bedenken, da die Lebensdauer von Objekten in Cocoa nicht so deterministisch ist, wie manche Leute zu glauben scheinen.Die verschiedenen Mac OS X-Frameworks selbst Wille Senden Sie Ihre Objekte -retain Und -autorelease, wodurch ihre Lebensdauer über das hinausgeht, was Sie sonst vielleicht vermuten würden.

Darüber hinaus werden Sie dies feststellen, wenn Sie auf die Objective-C-Garbage Collection umsteigen -finalize wird zu ganz anderen Zeiten – und in ganz anderen Kontexten – laufen als -dealloc tat.Zum einen findet die Finalisierung in einem anderen Thread statt, also Sie wirklich kippen sicher versenden -removeObserver:forKeyPath: zu einem anderen Objekt in a -finalize Methode.

Halten Sie sich an die Verwaltung von Speicher (und anderen knappen Ressourcen). -dealloc Und -finalize, und verwenden Sie ein separates -invalidate Methode, mit der ein Eigentümer einem Objekt an einem deterministischen Punkt mitteilen kann, dass Sie damit fertig sind;Machen Sie dort Dinge wie das Entfernen von KVO-Beobachtungen.Die Absicht Ihres Codes wird klarer und Sie müssen sich weniger um subtile Fehler kümmern.

Andere Tipps

Ein paar zusätzliche Informationen, die ich durch schmerzhafte Erfahrung gewonnen habe:Obwohl NSNotificationCenter bei der Ausführung unter Garbage Collection das Nullen schwacher Referenzen verwendet, ist dies bei KVO nicht der Fall.Daher können Sie bei der Verwendung von GC darauf verzichten, einen NSNotificationCenter-Beobachter zu entfernen (bei Verwendung von Retain/Release müssen Sie Ihren Beobachter trotzdem entfernen), aber Sie müssen trotzdem Ihre KVO-Beobachter entfernen, wie Chris beschreibt.

Ich stimme Chris auf jeden Fall in Bezug auf den Kommentar „Halten Sie sich an die Speicherverwaltung (und andere knappe Ressourcen) in -dealloc und -finalize ...“ zu.Ich sehe oft, dass Leute versuchen, NSTimer-Objekte in ihren Dealloc-Funktionen ungültig zu machen.Das Problem ist, dass NSTimer seine Ziele behält.Wenn das Ziel dieses NSTimers also „self“ ist, wird „dealloc“ niemals aufgerufen, was zu potenziell unangenehmen Speicherverlusten führen kann.

Ungültig machen in -invalidate und andere Speicherbereinigungen in Ihrem durchführen dealloc Und finalize.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top