web-dev-qa-db-fra.com

«[faible moi]» dans les fermetures de RXSwift

Dois-je utiliser [weak self] dans RXSwift subscribeNext fermetures?

J'ai le code:

    searchController.searchBar.rx_text.throttle(0.2, scheduler: MainScheduler.instance).subscribeNext { searchText in
        self.viewModel.searchForLocation(searchText)
    }.addDisposableTo(DisposelBag.sharedDisposelBag.disposeBag)

Dois-je le modifier pour qu'il y ait un [weak self] liste de capture au début de la fermeture? Comme ça:

    searchController.searchBar.rx_text.throttle(0.2, scheduler: MainScheduler.instance).subscribeNext { [weak self] searchText in
        self?.viewModel.searchForLocation(searchText)
    }.addDisposableTo(DisposelBag.sharedDisposelBag.disposeBag)
30
Rohan Panchal

Si la fermeture n'appartient pas à la classe, vous n'avez pas besoin d'utiliser [weak self].

Dans le cas de fermetures en ligne, la fermeture n'appartient pas à la classe mais à l'étendue dans laquelle elle se trouve et sera libérée lorsque l'étendue sera laissée.

Si la fermeture est passée, elle peut appartenir ou non à la classe (une propriété par exemple) et il est prudent d'utiliser [weak self] au cas où il appartient à la classe.

18
zaph

Oui, vous devez créer une capture faible de self si vous accédez à self dans la fermeture et il est possible que self devienne nil avant la fermeture. appelé.

Si une fermeture capture self puis self devient nil, lorsque la fermeture est appelée et tente d'accéder à cette self, vous obtenez une exception.

Crédit à scotteg, il a un exemple de projet sur GitHub: https://github.com/scotteg/TestRxSwiftClosures

Voir DetailViewController dans l'exemple.

Vous pouvez décommenter les deux autres exemples, un à la fois, pour voir les résultats. La première ne définit pas du tout de liste de capture et la seconde définit une capture unowned. Exécutez l'application et entrez du texte et appuyez sur Terminé dans les 5 secondes (il y a un délai de 5 secondes dans chaque fermeture). Les deux premiers exemples entraîneront la levée d'exceptions.

La règle de base est la suivante: si la capture (par exemple, self) peut être définie sur nil, comme si l'instance à laquelle elle fait référence est désallouée, définissez la capture comme weak . Sinon, si une fermeture et une capture à l'intérieur de cette fermeture se réfèrent toujours et se désallouent en même temps, définissez la capture comme unowned.

14
Son Nguyen

Vous voudrez utiliser [unowned self] ou [weak self] s'il y aura un cycle de référence fort. Les variables à l'intérieur des fermetures peuvent être "possédées" par la fermeture et resteront si la fermeture est, c'est pourquoi nous faisons [unowned self] ou [weak self].

0
jasonnoahchoi