Gdzie powinienem usunąć obserwatora NSNotification
w Swift, skoro viewDidUnload
i dealloc()
są niedostępne?
Gdzie powinienem usunąć obserwatora NSNotification
w Swift, skoro viewDidUnload
i dealloc()
są niedostępne?
Odpowiedzi:
Użyj poniższej metody, która działa tak samo jak dealloc
.
deinit {
// Release all resources
// perform the deinitialization
}
Deinitializer jest wywoływany bezpośrednio przed cofnięciem przydziału instancji klasy. Piszesz deinicjalizatory 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.
deinit
Metoda @Kampai dla ViewControllerA nie zostanie wywołana, gdy będzie push ViewControllerB.
deinit
for ViewControllerA zostanie wywołane tylko wtedy, gdy nie ma go na stosie kontrolera nawigacji. Na przykład: Przełączanie na rootViewController (jeśli rootViewController nie jest ViewControllerA)
deinit
. Idealne miejsce by zadzwonićfunc viewDidDisappear(_ animated: Bool)
Od iOS 9 (i OS X 10.11) nie musisz usuwać obserwatorów , jeśli jednak nie używasz obserwatorów blokowych. System zrobi to za Ciebie, ponieważ używa słabych zerowo referencji dla obserwatorów, gdzie tylko może.
A jeśli używasz obserwatorów opartych na blokach, upewnij się, że uchwyciłeś siebie słabo za pomocą [weak self]
listy przechwytywania zamknięcia i usuń obserwatora w deinit
metodzie. Jeśli nie użyjesz słabego odniesienia do siebie, deinit
metoda (a tym samym usunięcie tego obserwatora) nigdy nie zostanie wywołana, ponieważ Centrum powiadomień będzie utrzymywać silne odniesienie do niego przez czas nieokreślony.
Więcej informacji można znaleźć w informacjach o wydaniu Foundation dla systemu OS X 10.11 i iOS 9 .
Jeśli obserwator może być przechowywany jako odniesienie o słabym zerowaniu, 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 zwalniania.
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.
delegate = nil
w dealloc()
metodzie. Czy od teraz działa tak samo?
Możesz użyć trzech metod:
po popViewController
, z powrotem navigationController
lub dismissViewControllerAnimated
:
deinit {
print("Remove NotificationCenter Deinit")
NSNotificationCenter.defaultCenter().removeObserver(self)
}
viewDidDisappear
, usuń, gdy jest już następnym kontrolerem widoku:
override func viewDidDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
viewWillDisappear
- przed otwarciem kolejnego widoku:
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
Składnia Swift 3.0:
NotificationCenter.default.removeObserver(self)
W Swift 4.2 jest to jeden ze sposobów usuwania obserwatora
deinit {
NotificationCenter.default.removeObserver(self, name: Notification.Name.Identifier, object: nil)
}
skonfigurować powiadomienie addObserver w klasie viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(didReceivedItemDetail), name: Notification.Name.Identifier, object: nil)
}
Swift zapewnia metodę deinit, która jest wywoływana na wystąpieniach klas, zanim zostaną zniszczone.
Chcę również zaznaczyć, że powinieneś użyć tej metody:
func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)
Zamiast
func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol
Ten ostatni nie usunie obserwatora (ostatnio napotkałem ten problem). Pierwsza z nich usunie obserwatora, jeśli używasz iOS9.
dealloc
metodzie.
deinit {
NotificationCenter.default.removeObserver(self)
}
Szybki 5
Mam aplikację do czatu, więc za każdym razem, gdy przechodzę z mojego ChatLogViewController do innego ViewController, a następnie wracam, mam 1 dodatkowego obserwatora mojego powiadomienia z klawiatury. Aby to usunąć, usuwam wszystkich obserwatorów, gdy zmieniam viewController lub znikam z mojego chatLogViewController .
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(animated)
NotificationCenter.default.removeObserver(self)
}
Dobrze jest również dodać obserwatorów viewWillAppear()
i usunąć ichviewWillDisappear()