44

可能な限り Swift 構造体を使用しようとしています。また、クロージャーを取るメソッドを持つ RxSwift も使用しています。selfを参照するクロージャーを作成する構造体がある場合、それは強い参照サイクルを作成します。

import Foundation
import RxSwift

struct DoesItLeak {

    var someState: String = "initial value"
    var someVariable: Variable<String> = Variable("some stuff")

    let bag = DisposeBag()

    mutating func someFoo() {

        someVariable.subscribeNext { person in

            self.someState = "something"
        }
        .addDisposableTo(bag)
    }
}

どうすればこれを知ることができますか? 100,000 の DoesItLeak オブジェクトを作成し、それぞれで someFoo() を呼び出した場合、100,000 のオブジェクトが強い参照サイクルを持つと考えられます。つまり、これらのオブジェクトを含む DoesItLeak 配列を削除しても、オブジェクトはメモリに残ります。someFoo() を呼び出さなければ問題ありません。

変数はクラスです。したがって、xcode の Instruments の割り当てを使用し、Variable< String >でフィルタリングすることで、このメモリの問題を確認できます。

変数によるフィルタリング

ここに画像の説明を入力

次のように [weak self] を使用しようとすると、コンパイル エラーが発生します。

someVariable.subscribeNext { [weak self] person in

コンパイラエラーは「クラス以外の型にweakを適用することはできません」です

実際の/非サンプル コードでは、self を介してメソッドと変数にアクセスしますが、これはメモリの問題です。

DoesItLeak を構造体のままにして、このメモリの問題を解決するにはどうすればよいですか?

ご協力いただきありがとうございます。

4

4 に答える 4

18

ダレンがコメントに書いたように、「DoesItLeakは構造体にはなりません」 をDoesItLeak構造体にして、強い参照サイクルの問題を安全に解決することはできません。

構造体のような値型は、スタック フレームに存在します。クロージャとクラスは参照型です。

クロージャの強力な参照サイクル セクションで次のように説明されています。

この強い参照サイクルが発生するのは、クロージャがクラスと同様に参照型であるためです。

構造体にはVariable クラスがあり、参照するクロージャはを使用してクラスselfに格納されるため、強参照サイクルが作成されます。Apple ドキュメントの自動参照カウントの「クロージャの強い参照サイクルの解決」を参照してください。VariablesubscribeNext

于 2015-12-22T15:23:05.507 に答える