jeśli powiesz obiektowi c, aby usunął Observers: dla ścieżki klucza i ta ścieżka klucza nie została zarejestrowana, złamie to sads. lubić -
„Nie można usunąć obserwatora ze ścieżki klucza„ theKeyPath ”, ponieważ nie jest on zarejestrowany jako obserwator.”
czy istnieje sposób określenia, czy obiekt ma zarejestrowanego obserwatora, więc mogę to zrobić
if (object has observer){
remove observer
}
else{
go on my merry way
}
objective-c
cocoa
key
key-value-observing
Aran Mulholland
źródło
źródło
addObserver:
naviewWillAppear:
i odpowiednioremoveObserver:
sięviewWillDisappear:
, że połączenia zostały prawidłowo połączone. Muszę szybko naprawić, więc zaimplementuję rozwiązanie try-catch i zostawię komentarz, aby dokładniej zbadać przyczynę.Odpowiedzi:
Spróbuj złapać wokół wywołania removeObserver
źródło
Prawdziwe pytanie brzmi: dlaczego nie wiesz, czy to obserwujesz, czy nie.
Jeśli robisz to w klasie obserwowanego obiektu, przestań. Cokolwiek obserwuje, oczekuje, że będzie to obserwować. Jeśli odetniesz powiadomienia obserwatora bez jego wiedzy, spodziewaj się, że coś się zepsuje; dokładniej, spodziewaj się, że stan obserwatora zgaśnie, ponieważ nie otrzyma on aktualizacji z poprzednio obserwowanego obiektu.
Jeśli robisz to w klasie obserwowanego obiektu, po prostu pamiętaj, które obiekty obserwujesz (lub, jeśli kiedykolwiek obserwujesz tylko jeden obiekt, czy go obserwujesz). Zakłada się, że obserwacja jest dynamiczna i między dwoma inaczej niepowiązanymi obiektami; jeśli obserwator jest właścicielem obserwowanego, po prostu dodaj obserwatora po utworzeniu lub zachowaniu obserwowanego i usuń obserwatora przed zwolnieniem obserwowanego.
Dodawanie i usuwanie obiektu jako obserwatora powinno zwykle mieć miejsce w klasie obserwatora, a nigdy w klasie obserwowanego obiektu.
źródło
FWIW,
[someObject observationInfo]
wydaje się, żenil
jeślisomeObject
nie ma żadnych obserwatorów. Nie ufałbym jednak temu zachowaniu, ponieważ nie widziałem tego udokumentowanego. Nie wiem też, jak czytać,observationInfo
aby uzyskać konkretnych obserwatorów.źródło
objectAtIndex:
nie daje pożądanego rezultatu.)NSKeyValueObserving.h
Jedynym sposobem na to jest ustawienie flagi podczas dodawania obserwatora.
źródło
Kiedy dodajesz obserwatora do obiektu, możesz dodać go do
NSMutableArray
takiego:Jeśli chcesz anulować obserwację obiektów, możesz zrobić coś takiego:
Pamiętaj, że jeśli nie obserwujesz pojedynczego obiektu, usuń go z
_observedObjects
tablicy:źródło
NSHashTable
/,NSMapTable
aby zachować słabe odniesienia.Moim zdaniem - działa to podobnie jak mechanizm retainCount. Nie możesz być pewien, że w tej chwili masz swojego obserwatora. Nawet jeśli sprawdzisz: self.observationInfo - nie można wiedzieć na pewno, że trzeba będzie / nie będzie miała obserwatorów w przyszłości.
Podobnie jak retainCount . Może metoda observationInfo nie jest aż tak bezużyteczna, ale używam jej tylko do debugowania.
W rezultacie - po prostu trzeba to robić jak w zarządzaniu pamięcią. Jeśli dodałeś obserwatora - po prostu usuń go, gdy go nie potrzebujesz. Podobnie jak przy użyciu metod viewWillAppear / viewWillDisappear itp. Na przykład:
Potrzebujesz pewnych specyficznych kontroli - zaimplementuj własną klasę, która obsługuje tablicę obserwatorów i używaj jej do kontroli.
źródło
[self removeObserver:nil forKeyPath:@""];
musi iść przed:[super viewWillDisappear:animated];
- (void) setupSomething { [super setupSomething]; … } - (void) tearDownSomething { … [super tearDownSomething]; }
[someObject observationInfo]
powrócić,nil
jeśli nie ma obserwatora.źródło
Cały sens wzorca obserwatora polega na tym, aby pozwolić obserwowanej klasie na „zapieczętowanie” - nie wiedząc lub nie dbając o to, czy jest obserwowana. Próbujesz wyraźnie złamać ten wzorzec.
Czemu?
Problem, który masz, polega na tym, że zakładasz, że jesteś obserwowany, a tak nie jest. Ten obiekt nie rozpoczął obserwacji. Jeśli chcesz, aby Twoja klasa miała kontrolę nad tym procesem, powinieneś rozważyć użycie centrum powiadomień. W ten sposób Twoja klasa ma pełną kontrolę nad tym, kiedy można obserwować dane. Dlatego nie obchodzi go, kto patrzy.
źródło
Nie jestem fanem tego rozwiązania typu try catch, więc przez większość czasu tworzę metodę subskrybowania i anulowania subskrypcji dla określonego powiadomienia w tej klasie. Na przykład te dwie metody subskrybują lub anulują subskrypcję obiektu do globalnego powiadomienia z klawiatury:
Wewnątrz tych metod używam własności prywatnej, która jest ustawiona na true lub false w zależności od stanu subskrypcji, jak na przykład:
źródło
Oprócz odpowiedzi Adama chciałbym zasugerować użycie takiego makra
przykład użycia
źródło