5

Mam klasę ViewController, która ma właściwość, która jest modelem, który chcę obserwować jako właściwości przy zmianie modelu. Wewnątrz obiektu modelu mam właściwość, która jest okresowo aktualizowana w tle mojej aplikacji. Podczas aktualizacji muszę wykonać kod w mojej jednostce ViewController.Kiedy należy wywołać removeObserver: forKeyPath z zamykającej klasy ViewController, która obserwuje trwałą klasę Model?

Aby to zrobić, tworzę obserwatora na moim modelu z mojej metody ViewControllerviewDidLoad.

[ModelObject addObserver:self 
       forKeyPath:@"State" 
       options:NSKeyValueObservingOptionNew 
       context:nil]; 

Jak widać, jest to nic specjalnego, a metoda obserwacji zachowuje się jak powinien, o ile mogę zostawić widoku wyświetlanego na ekranie to. Jeśli usunę powyższy widok z widoku nadrzędnego, otrzymam komunikat o błędzie EXC_BAD_ACCESS po zmianie właściwości ModelObject instancji Mode. W szczególności moja aplikacja ulega awarii w wierszu aktualizującym właściwość Mode, a najbardziej nieprzydatny jest EXC_BAD_ACCESS w następującym wierszu kodu wewnątrz instancji ModelObject.

//This is located in a method that periodically toggles the value of "State" 
[self setState: 2]; 

Przypuszczam rozwiązanie tego problemu jest zadzwonić [ModelObject removeObserver: self forKeyPath:@"State"] gdzieś w moim ViewController gdy zostaje usunięta z tablicy to rodzic subview. Jednak dodałem tę linię kodu w mojej metodzie viewDidUnload, ale odkryłem, że metoda viewDidUnload nie jest wywoływana. Nie jestem pewien, czy to właściwe miejsce, ale musi gdzieś pójść.

Co mogę zrobić niepoprawnie? Wiem, że problem jest związany z KVO, ponieważ jeśli usunę obserwację, aplikacja działa bez problemu. Moja instancja modelu może przełączać tę wartość tak, jak chce, a moja aplikacja nigdy się nie zawiesza. Co powinienem zrobić, aby mieć pewność, że mój obserwator zostanie usunięty poprawnie, gdy widok obserwacyjny zostanie usunięty z macierzy podrzędnej jego rodzica?

Odpowiedz

9

ja generalnie lubię umieścić addObserver: i removeObserver: w viewWillAppear: i viewWillDisappear:. Uważam, że są to bardziej niezawodne bookends niż viewDidLoad i viewDidUnload.

+0

Ah, idealnie. Moja aplikacja działa teraz tak, jak powinna. – RLH

+0

Ja po drugie to rozwiązanie. 'viewDidUnload:' jest wywoływane, gdy odbierane jest ostrzeżenie o pamięci i nie odpowiada 'viewDidLoad:' jak można pomyśleć. –

+0

Jest to problematyczne podczas testowania jednostkowego kontrolera widoku bez dodawania go do hierarchii widoków. –

1

Należy usunąć go w kontroler widoku za -dealloc

+1

Powinieneś to zrobić tylko, jeśli dodałeś siebie jako obserwatora przy tworzeniu obiektu ('init ...' i 'awakeFromNib'). W przeciwnym razie możesz uzyskać brak równowagi. Na przykład 'viewDidLoad' może być wywołane wielokrotnie więcej niż' dealloc'. –

+0

Tak, to prawda, i zawsze to robię. – jsd

Powiązane problemy