dealloc w Swift

145

Chciałbym przeprowadzić pewne porządki pod koniec życia kontrolera widoku, a mianowicie usunąć NSNotificationCenterpowiadomienie. Implementacja deallocpowoduje błąd kompilatora Swift:

Cannot override 'dealloc' which has been marked unavailable

Jaki jest preferowany sposób porządkowania pod koniec życia obiektu w Swift?

Kyle Clegg
źródło

Odpowiedzi:

333
deinit {
    // perform the deinitialization
}

Z dokumentacji Swift :

Deinitializer jest wywoływany bezpośrednio przed cofnięciem przydziału instancji klasy. Piszesz deinitializatory za pomocą słowa kluczowego deinit, podobnie jak w przypadku pisania intializatorów za pomocą słowa kluczowego init. Deinicjatory są dostępne tylko dla typów klas.

Zazwyczaj nie ma potrzeby ręcznego czyszczenia, gdy Twoje instancje są zwalniane. Jednak podczas pracy z własnymi zasobami może być konieczne samodzielne wykonanie dodatkowych czynności porządkowych. Na przykład, jeśli utworzysz klasę niestandardową w celu otwarcia pliku i zapisania w nim danych, może być konieczne zamknięcie pliku przed zwolnieniem instancji klasy.

Kyle Clegg
źródło
45
deinit {
    // perform the deinitialization
}

jest poprawną odpowiedzią na szybkie „dealloc”.

Jednak dobrze jest zaznaczyć, że nowością w iOS 9 jest to, że NSNotificationCenter nie wymaga już czyszczenia!

https://developer.apple.com/library/content/releasenotes/Foundation/RN-FoundationOlderNotes/index.html#X10_11Notes

NSNotificationCenter

W OS X 10.11 i iOS 9.0 NSNotificationCenter i NSDistributedNotificationCenter nie będą już wysyłać powiadomień do zarejestrowanych obserwatorów, którzy mogą zostać zwolnieni. Jeśli obserwator może być przechowywany jako odniesienie słabo zerujące, podstawowa pamięć będzie przechowywać obserwatora jako słabe odniesienie zerujące, alternatywnie, jeśli obiekt nie może być przechowywany słabo (tj. Ma niestandardowy mechanizm zatrzymania / zwolnienia, który uniemożliwiłby działanie środowiska wykonawczego przed słabym przechowywaniem obiektu) będzie przechowywać obiekt jako niezbyt słabe odniesienie zerujące. Oznacza to, że obserwatorzy nie muszą wyrejestrowywać się w swojej metodzie cofnięcia przydziału. Następne powiadomienie, które zostanie skierowane do tego obserwatora, wykryje zerowane odniesienie i automatycznie wyrejestruje obserwatora. Jeśli obiekt może mieć słabe odniesienia, powiadomienia nie będą już wysyłane do obserwatora podczas zwalniania alokacji; poprzednie zachowanie polegające na otrzymywaniu powiadomień podczas zwalniania przydziału jest nadal obecne w przypadku słabo zerujących obserwatorów odniesienia. Obserwatorzy blokowi za pośrednictwem metody - [NSNotificationCenter addObserverForName: object: queue: usingBlock] nadal muszą być wyrejestrowani, gdy nie są już w użyciu, ponieważ system nadal posiada silne odniesienie do tych obserwatorów. Przedwczesne usuwanie obserwatorów (słabo wskazanych lub zerowanych) jest nadal obsługiwane. CFNotificationCenterAddObserver nie jest zgodny z tym zachowaniem, ponieważ obserwator może nie być obiektem. Obserwatorzy blokowi za pośrednictwem metody - [NSNotificationCenter addObserverForName: object: queue: usingBlock] nadal muszą być wyrejestrowani, gdy nie są już w użyciu, ponieważ system nadal posiada silne odniesienie do tych obserwatorów. Przedwczesne usuwanie obserwatorów (słabo wskazanych lub zerowanych) jest nadal obsługiwane. CFNotificationCenterAddObserver nie jest zgodny z tym zachowaniem, ponieważ obserwator może nie być obiektem. Obserwatorzy blokowi za pośrednictwem metody - [NSNotificationCenter addObserverForName: object: queue: usingBlock] nadal muszą być wyrejestrowani, gdy nie są już w użyciu, ponieważ system nadal posiada silne odniesienie do tych obserwatorów. Przedwczesne usuwanie obserwatorów (słabo wskazanych lub zerowanych) jest nadal obsługiwane. CFNotificationCenterAddObserver nie jest zgodny z tym zachowaniem, ponieważ obserwator może nie być obiektem.

ale zwróć uwagę na poniższe punkty dotyczące silnych odniesień, więc i tak możesz się martwić o czyszczenie ...?

James
źródło
3
Jeśli blok powiadomień nie ma silnego odniesienia, musisz usunąć obserwatora.
TigerCoding
+1 za brak konieczności czyszczenia obserwatorów. Ważne, aby wiedzieć! Wszystkie odniesienia do przechwytywania są słabe, więc nigdy nie muszę się tym zajmować.
n13
2
Bloki powiadomień zawsze wydają się mieć silne odniesienia zgodnie z dokumentacją. Tak więc: jeśli używasz bloków do obsługi powiadomień, musisz wyrejestrować się z nich w deinit.
marsbear
22

https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Deinitialization.html

Swift automatycznie zwalnia Twoje instancje, gdy nie są już potrzebne, aby zwolnić zasoby. Swift obsługuje zarządzanie pamięcią instancji poprzez automatyczne liczenie referencji (ARC), zgodnie z opisem w sekcji Automatyczne liczenie referencji. Zazwyczaj nie ma potrzeby ręcznego czyszczenia, gdy Twoje instancje są zwalniane. Jednak podczas pracy z własnymi zasobami może być konieczne samodzielne wykonanie dodatkowych czynności porządkowych. Na przykład, jeśli utworzysz klasę niestandardową w celu otwarcia pliku i zapisania w nim danych, może być konieczne zamknięcie pliku przed zwolnieniem instancji klasy.

Definicje klas mogą mieć co najwyżej jeden deinicjator na klasę. Deinicjalizator nie przyjmuje żadnych parametrów i jest napisany bez nawiasów:

deinit {
    // perform the deinitialization
}
Varsha Vijayvargiya
źródło
2

usunięcie obserwatora jest wymagane przed cofnięciem alokacji, w przeciwnym razie doszłoby do awarii. Można to zrobić za pomocą

deinit {
    // perform the deinitialization
    print("deinit")

    removeObserver(self, forKeyPath: kSelectedViewControllerKey, context: nil)
    removeObserver(self, forKeyPath: kSelectedIndexKey, context: nil)

}
Szpieg
źródło
-2

Zachowaj ostrożność podczas wywoływania metody z innej klasy z deinit , prawdopodobnie zakończy się to awarią

Jeba Moses
źródło
1
Głosowano w dół, ponieważ niekoniecznie tak musi być. Od ref. docs : Ponieważ instancja jest zwalniana dopiero po wywołaniu jej deinitializer, deinitializer może uzyskać dostęp do wszystkich właściwości instancji, do której jest wywoływana i może modyfikować swoje zachowanie na podstawie tych właściwości (np. wyszukanie nazwy pliku, który musi zamknięte).
superjos