Où devrais-je retirer l'observateur de NSNotification
dans Swift, puisque viewDidUnload
et dealloc()
ne sont pas disponibles?
Utilisez la méthode ci-dessous qui fonctionne de la même manière que dealloc
.
deinit {
// Release all resources
// perform the deinitialization
}
Un désinitialiseur est appelé immédiatement avant qu'une instance de classe ne soit désallouée. Vous écrivez desinitialiseurs avec le mot clé deinit, similaire à la façon dont les initiaux sont écrits avec le mot clé init. Les déinitialiseurs ne sont disponibles que sur les types de classe.
À partir de iOS 9 (et de OS X 10.11), vous n'avez pas besoin de supprimer les observateurs vous-même, si vous n’utilisez pas d’observateurs basés sur des blocs. Le système le fera pour vous, car il utilise les références faibles pour les observateurs, dans la mesure du possible.
Et si vous utilisez des observateurs basés sur des blocs, assurez-vous de vous capturer faiblement en utilisant [weak self]
dans la liste de capture de la fermeture, et supprime l'observateur dans la méthode deinit
. Si vous n'utilisez pas de référence faible à self, la méthode deinit
(et donc le retrait de cet observateur) ne sera jamais appelée, car le Centre de notification gardera une référence forte à cette référence indéfiniment.
Pour plus d'informations, consultez la page Notes de version de Foundation pour OS X v10.11 et iOS 9 .
Si l’observateur peut être stocké en tant que référence de mise à zéro faible, le stockage sous-jacent le stockera en tant que référence de mise à zéro faible, ou si l’objet ne peut pas être stocké de manière faible (c’est-à-dire qu’il dispose d’un mécanisme de conservation/libération personnalisé qui empêcherait le temps d’exécution. de pouvoir stocker l’objet faiblement), il stockera l’objet en tant que référence de réduction à zéro non faible. Cela signifie que les observateurs ne sont pas tenus de se désinscrire de leur méthode de désallocation.
Les observateurs basés sur des blocs via la méthode - [NSNotificationCenter addObserverForName: object: queue: usingBlock] doivent toujours être désenregistrés lorsqu'ils ne sont plus utilisés, car le système conserve toujours une référence forte à ces observateurs.
Vous pouvez utiliser trois méthodes:
1 - après popViewController
, retour navigationController
ou dismissViewControllerAnimated
:
deinit {
print("Remove NotificationCenter Deinit")
NSNotificationCenter.defaultCenter().removeObserver(self)
}
ou
2 - viewDidDisappear
, supprimez-le s'il est déjà le prochain contrôleur de vue:
override func viewDidDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
ou
3 - viewWillDisappear
- avant d’ouvrir la vue suivante:
override func viewWillDisappear(animated: Bool) {
NSNotificationCenter.defaultCenter().removeObserver(self)
}
syntaxe Swift 3.0:
NotificationCenter.default.removeObserver(self)
Dans Swift 4.2, C’est l’un des moyens de supprimer l’observateur
deinit {
NotificationCenter.default.removeObserver(self, name: Notification.Name.Identifier, object: nil)
}
configurer la notification addObserver dans la classe viewDidLoad
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(didReceivedItemDetail), name: Notification.Name.Identifier, object: nil)
}
Swift fournit une méthode deinit qui est appelée sur les instances de classes avant leur destruction.
Je tiens également à souligner que vous devriez utiliser cette méthode:
func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)
Au lieu de
func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol
Ce dernier n’éliminera pas l’observateur (récemment exploré ce problème). Le premier va supprimer l'observateur si vous utilisez iOS9.
C'est également bien si vous ajoutez votre observateur dans viewWillAppear()
et le supprimez dans viewWillDisappear()