web-dev-qa-db-ja.com

RXSwiftクロージャーの「[weak self]」

RXSwift subscribeNextクロージャー内で[weak self]を使用する必要がありますか?

私はコードを持っています:

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

クロージャの最初に[weak self]キャプチャリストがあるように変更する必要がありますか?このような:

    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

クロージャがクラスによって所有されていない場合、[weak self]を使用する必要はありません。

インラインクロージャの場合、クロージャはクラスによって所有されているのではなく、クラスが属するスコープによって所有されており、スコープが終了すると解放されます。

クロージャが渡された場合、クラス(たとえばプロパティ)が所有している場合と所有していない場合があり、クラスが所有している場合は[weak self]を使用するのが賢明です。

18
zaph

はい、クロージャ内でselfにアクセスし、クロージャが呼び出される前にselfselfになる可能性がある場合、nilの弱いキャプチャを作成する必要があります。

クロージャがselfをキャプチャし、selfnilになった場合、クロージャが呼び出されてそのselfにアクセスしようとすると、例外が発生します。

Scottegの功績により、彼はGitHubにサンプルプロジェクトを用意しています。 https://github.com/scotteg/TestRxSwiftClosures

例のDetailViewControllerを参照してください。

他の2つの例のコメントを一度に1つずつ解除して、結果を確認できます。最初のものはキャプチャリストをまったく定義せず、2番目のものはunownedキャプチャを定義します。アプリを実行し、テキストを入力して、5秒以内に[完了]をタップします(閉鎖ごとに5秒の遅延があります)。最初の2つの例では、例外がスローされます。

基本的なルールは次のとおりです。たとえば、参照するインスタンスの割り当てが解除されるなど、キャプチャ(selfなど)をnilに設定できる場合は、キャプチャをweakとして定義します。それ以外の場合、クロージャとそのクロージャ内のキャプチャが常にalwaysを参照し、同時に割り当て解除される場合は、キャプチャをunownedとして定義します。

14
Son Nguyen

強力な参照サイクルがある場合は、[unowned self]または[weak self]を使用する必要があります。クロージャー内の変数は、クロージャーによって「所有」され、クロージャーが存在する場合は固定されます。そのため、[unowned self]または[weak self]を実行します。

0
jasonnoahchoi