2011-09-03 11 views
198

W mojej małej aplikacji na iPada mam funkcję "języka przełączania", która używa obserwatora. Każdy kontroler widoku rejestruje się wraz z moim obserwatorem podczas jego viewDidLoad:.Niestandardowe dealloc i ARC (Objective-C)

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [observer registerObject:self]; 
} 

Gdy użytkownik kliknie przycisk „Zmień język”, nowy język jest przechowywany w moim modelu i obserwator został powiadomiony i wywołuje selektor updateUi: na statutową obiektów.

Działa to bardzo dobrze, z wyjątkiem sytuacji, gdy mam kontrolerów widoku w kontrolce TabBarController. Dzieje się tak, ponieważ po załadowaniu paska kart pobiera ikony kart ze swoich kontrolerów podrzędnych bez inicjowania widoków, dlatego viewDidLoad: nie jest wywoływana, więc te kontrolery widoku nie otrzymują powiadomień o zmianie języka. Z tego powodu przeniosłem swoje wywołania registerObject: do metody .

Powrót, gdy użyłem viewDidLoad: do zarejestrowania się z moim obserwatorem, użyłem viewDidUnload: do wyrejestrowania. Odkąd teraz rejestruję się w init, ma sens, aby wyrejestrować się w dealloc.

Ale tu jest mój problem. Kiedy piszę:

- (void) dealloc 
{ 
    [observer unregisterObject:self]; 
    [super dealloc]; 
} 

otrzymuję ten błąd:

ARC forbids explicit message send of 'dealloc'

Ponieważ muszę zadzwonić [super dealloc] celu zapewnienia superklasy oczyścić prawidłowo, ale ARC zabrania, jestem teraz zakleszczony. Czy istnieje inny sposób na uzyskanie informacji, kiedy mój obiekt umiera?

+0

Na marginesie - sytuacja jak może to spowodować wyciek pamięci, który nie byłby widoczny w narzędziu Wycieki. Jeśli moduł danych zachowuje odwołanie do obserwatora (co jest domyślną rzeczą w ARC, nawet w przypadku ivars), dealloc nigdy nie zostanie wywołany, ponieważ liczba zatrzymań będzie większa niż zero. Dlatego konieczne może być ręczne wyrejestrowanie obserwatora, aby umożliwić wywołanie dealloc w pierwszej kolejności. –

+0

Zaimplementowałem coś podobnego dla opcji prawej i lewej ręki. Jedynym VC wymagającym wiadomości jest aktualnie wyświetlany. Inni patrzą na model w viewDidLoad lub viewDidAppear, aby dokonać zmian w interfejsie. Może coś takiego będzie działało lepiej. –

+0

@BlazejCzapp od kiedy używa UITabBarController, i powiedzmy, że UITabBarController zawsze będzie zawierał referencje do zarejestrowanego kontrolera (jak myślę, jest w przypadku jego "potomnych" kontrolerów), czy wyciek pamięci nadal będzie problemem? Nie widzę, kiedy będzie przydzielony zarejestrowany kontroler. Dzięki – Objectif

Odpowiedz

400

Podczas korzystania ARC, po prostu nie nazywają [super dealloc] wyraźnie - kompilator obsługuje to dla ciebie (jak opisano w Clang LLVM ARC document, chapter 7.1.2):

- (void) dealloc 
{ 
    [observer unregisterObject:self]; 
    // [super dealloc]; //(provided by the compiler) 
} 
+2

Jeśli widok zawiera odniesienie do obserwatora, a obserwator odwołuje się do widoku, to mamy odniesienie kołowe. Tak więc liczba odwołań do widoku jest większa niż 0, a 'dealloc' nigdy nie jest wywoływana. Czy ma sens nazywanie "[observer unregisterObject: self]" w dealloc? czego mi brakuje? – user443854

+0

thats chcesz pracować. ponieważ sam obserwator odwołuje się do kontrolera. to powstrzyma dealloc przed otrzymaniem wezwania – hasan83

Powiązane problemy