87

Jak usunąć obserwatora z obiektu pod numerem ARC? Czy po prostu dodajemy obserwatora i zapominamy o jego usunięciu? Jeśli nie będziemy już zarządzać pamięcią ręcznie, skąd zrezygnujemy z obserwacji?KVO i ARC jak usunąćObserwer

Na przykład na kontrolerze widoku:

[self.view addObserver:self 
      forKeyPath:@"self.frame" 
       options:NSKeyValueObservingOptionNew 
       context:nil]; 

Wcześniej nazwałbym removeObserver: w dealloc metody kontrolera widoku za.

+4

pamiętać, że to bardzo zły pomysł, aby KVO .frame. Jak napisano w innym miejscu przez inżynierów Apple na StackOverflow, właściwość ramki UIKit nie jest zgodna z KVO. Kiedy działa, to tylko przez przypadek. – steipete

+2

Czy twoja keyPath nie powinna być ramką '@ 'zamiast' @' self.frame? – Besi

Odpowiedz

126

Nadal można wdrożyć -dealloc pod ARC, który wydaje się być odpowiednim miejscem do usunięcia obserwacji kluczowych wartości. Po prostu nie wołaj już [super dealloc] z tej metody.

Jeśli wcześniej zastępowałeś -release, robiłeś różne rzeczy w niewłaściwy sposób.

+1

Czy jesteś tego pewien? Cytuję z http://clang.llvm.org/docs/AutomaticReferenceCounting.html#ownership.spelling.property, sekcja 7.1.2. dealloc: "Uzasadnienie: nawet jeśli ARC automatycznie niszczy instancyjne zmienne, wciąż istnieją uzasadnione powody, aby napisać metodę dealloc, taką jak uwolnienie nieprzenośnych zasobów. Niemożliwość wywołania [super dealok] w takiej metodzie jest prawie zawsze błędem." –

+0

@ElisevanLooij Tak, to prawda. Jeśli wywodzisz się z tej klasy, wydaje się oczywiste, że musisz wywołać "[super dealok]". Kto jeszcze powinien to dla ciebie zrobić. –

+0

@ElisevanLooij Ups, cóż, powinienem sprawdzić wcześniej. Niedozwolone jest wywoływanie "[super dealok]" metodą dealloc. Nie wiem, jak to by działało, gdy podklasy wspomnianej klasy. Być może wskazane jest użycie 'sfinalizowania' zamiast (gdzie nazywasz' [super finalize] ') –

-2

Elsewhere na przepełnieniu stosu, Chris Hanson zaleca użycie metody finalizacji w tym celu i wdrożenie osobnej metody unieważnienia, aby właściciele mogli powiedzieć obiektom, że są zrobione. W przeszłości uważałem, że rozwiązania Hansona są dobrze przemyślane, więc zamierzam to zrobić.

+13

Zauważ, że miał na myśli zbiór śmieci tam, a nie ARC (jego odpowiedź została napisana w 2008 roku). Podczas usuwania śmieci '-dealloc' nigdy nie jest wywoływany. W ARC jest. Całkowicie dopuszczalne jest usuwanie obserwatorów KVO w '-dealloc', ponieważ Chris Lattner (który wie o czym mówi) wskazuje na forach programistów Apple tutaj: https://devforums.apple.com/message/475850 –

+3

Dzięki Brad, za wykonanie cała ta praca. Nie, aby sfinalizować, tak, aby anulować, ale bez [super deal]. Proste naprawdę, kiedy już to wiesz. Hej, @drunknbass, zaakceptuj odpowiedź mężczyzny! –

0

to zrobić z tym kodem

- (void)dealloc 
{ 
@try{ 
    [self.uAvatarImage removeObserver:self forKeyPath:@"image" context:nil]; 
} @catch(id anException) { 
    //do nothing, obviously it wasn't attached because an exception was thrown 
} 
}  
+2

Jaki jest sens obsługi wyjątków w 'dealloc'? Jest już za późno, aby cokolwiek z tym zrobić. – Abizern

+0

Jaki jest cel usuwania obserwatorów ze zmiennej instancji w dealloc? Ten uAvatarImage zostanie zwolniony wkrótce wraz z obserwatorami, którzy zasubskrybowali jego kluczowe ścieżki. – shoumikhin

+0

@shoumikhin Używam ARC i musiałem usunąć obserwatora metodą dealloc. Mam to samo pytanie, które masz. Jednak po uruchomieniu wielu instancji klasy w końcu dostałem błąd exc_bad_address. Wykonanie tego rozwiązało problem. Również odpowiedź stąd http://stackoverflow.com/questions/32490808/com-apple-nsurlsession-work-exc-bad-access-crash-debugging pomogła mi odkryć problem. – mac10688