Wenn Sie einem objektiven c-Objekt anweisen, Observer zu entfernen: Wenn ein Schlüsselpfad und dieser Schlüsselpfad nicht registriert wurden, werden die Sads geknackt. mögen -
'Ein Beobachter für den Schlüsselpfad "theKeyPath" kann nicht entfernt werden, da er nicht als Beobachter registriert ist.'
Gibt es eine Möglichkeit festzustellen, ob ein Objekt einen registrierten Beobachter hat, damit ich dies tun kann?
if (object has observer){
remove observer
}
else{
go on my merry way
}
objective-c
cocoa
key
key-value-observing
Aran Mulholland
quelle
quelle
addObserver:
inviewWillAppear:
und entsprechendremoveObserver:
inviewWillDisappear:
wurden die Anrufe korrekt gepaart. Ich muss eine schnelle Lösung finden, damit ich die Try-Catch-Lösung implementieren und einen Kommentar hinterlassen kann, um die Ursache weiter zu untersuchen.Antworten:
Versuchen Sie es mit Ihrem removeObserver-Aufruf
quelle
Die eigentliche Frage ist, warum Sie nicht wissen, ob Sie es beobachten oder nicht.
Wenn Sie dies in der Klasse des beobachteten Objekts tun, stoppen Sie. Was auch immer es beobachtet, erwartet, es weiter zu beobachten. Wenn Sie die Benachrichtigungen des Beobachters ohne dessen Wissen abschneiden, müssen Sie damit rechnen, dass die Dinge kaputt gehen. Erwarten Sie insbesondere, dass der Status des Beobachters veraltet ist, da er keine Aktualisierungen vom zuvor beobachteten Objekt erhält.
Wenn Sie dies in der Klasse des Beobachtungsobjekts tun, merken Sie sich einfach, welche Objekte Sie beobachten (oder, wenn Sie immer nur ein Objekt beobachten, ob Sie es beobachten). Dies setzt voraus, dass die Beobachtung dynamisch ist und zwischen zwei ansonsten nicht verwandten Objekten liegt; Wenn der Beobachter das Beobachtete besitzt, fügen Sie den Beobachter einfach hinzu, nachdem Sie das Beobachtete erstellt oder beibehalten haben, und entfernen Sie den Beobachter, bevor Sie das Beobachtete freigeben.
Das Hinzufügen und Entfernen eines Objekts als Beobachter sollte normalerweise in der Klasse des Beobachters und niemals in der Klasse des beobachteten Objekts erfolgen.
quelle
FWIW
[someObject observationInfo]
scheint zu sein,nil
wennsomeObject
es keine Beobachter gibt. Ich würde diesem Verhalten jedoch nicht vertrauen, da ich es nicht dokumentiert gesehen habe. Außerdem kann ich nicht lesenobservationInfo
, um bestimmte Beobachter zu finden.quelle
objectAtIndex:
liefert nicht das gewünschte Ergebnis.)NSKeyValueObserving.h
Die einzige Möglichkeit, dies zu tun, besteht darin, ein Flag zu setzen, wenn Sie einen Beobachter hinzufügen.
quelle
Wenn Sie einem Objekt einen Beobachter hinzufügen, können Sie ihn
NSMutableArray
wie folgt hinzufügen :Wenn Sie die Objekte nicht beobachten möchten, können Sie Folgendes tun:
Denken Sie daran, wenn Sie ein einzelnes Objekt nicht beobachten, entfernen Sie es aus dem
_observedObjects
Array:quelle
NSHashTable
/NSMapTable
zu verwenden, um die schwachen Referenzen zu behalten.Meiner Meinung nach funktioniert dies ähnlich wie der RetainCount-Mechanismus. Sie können nicht sicher sein, ob Sie im Moment Ihren Beobachter haben. Selbst wenn Sie Folgendes überprüfen: self.observationInfo - Sie können nicht sicher sein, ob Sie in Zukunft Beobachter haben / nicht haben werden.
Wie RetainCount . Vielleicht ist die ObservationInfo- Methode nicht genau so nutzlos, aber ich verwende sie nur für Debug-Zwecke.
Als Ergebnis müssen Sie dies nur wie bei der Speicherverwaltung tun. Wenn Sie einen Beobachter hinzugefügt haben, entfernen Sie ihn einfach, wenn Sie ihn nicht benötigen. Wie bei der Verwendung der Methoden viewWillAppear / viewWillDisappear usw. Z.B:
Und wenn Sie einige spezifische Prüfungen benötigen, implementieren Sie Ihre eigene Klasse, die eine Reihe von Beobachtern verarbeitet, und verwenden Sie sie für Ihre Prüfungen.
quelle
[self removeObserver:nil forKeyPath:@""];
muss vorher gehen:[super viewWillDisappear:animated];
- (void) setupSomething { [super setupSomething]; … } - (void) tearDownSomething { … [super tearDownSomething]; }
[someObject observationInfo]
Rückkehr,nil
wenn kein Beobachter anwesend ist.quelle
Der springende Punkt des Beobachtermusters ist, dass eine beobachtete Klasse "versiegelt" werden kann - um nicht zu wissen oder sich darum zu kümmern, ob sie beobachtet wird. Sie versuchen explizit, dieses Muster zu brechen.
Warum?
Das Problem, das Sie haben, ist, dass Sie davon ausgehen, dass Sie beobachtet werden, wenn Sie es nicht sind. Dieses Objekt hat die Beobachtung nicht gestartet. Wenn Sie möchten, dass Ihre Klasse die Kontrolle über diesen Prozess hat, sollten Sie das Benachrichtigungscenter verwenden. Auf diese Weise hat Ihre Klasse die volle Kontrolle darüber, wann Daten beobachtet werden können. Daher ist es egal, wer zuschaut.
quelle
Ich bin kein Fan dieser Try-Catch-Lösung. Was ich also meistens mache, ist, dass ich eine Methode zum Abonnieren und Abbestellen für eine bestimmte Benachrichtigung innerhalb dieser Klasse erstelle. Mit diesen beiden Methoden können Sie das Objekt beispielsweise für die globale Tastaturbenachrichtigung abonnieren oder abbestellen:
Innerhalb dieser Methoden verwende ich eine private Eigenschaft, die je nach Abonnementstatus wie folgt auf true oder false gesetzt ist:
quelle
Zusätzlich zu Adams Antwort möchte ich vorschlagen, ein solches Makro zu verwenden
Anwendungsbeispiel
quelle