2017-11-15 11 views
1

注意:私は、強い参照サイクルを避けるという点について、(非常に多くの)回答と記事の多くを読んできました。しかし、私はこれらのサイクルを避ける特定の副産物をどのように扱うかについてのガイダンスを探しています。Swift - クロージャベースのコンフィグレーションでの強い参照サイクルの回避

次の例では、クラスFooはクロージャを使用して構成されるように設計されています。クロージャへの参照は、後で使用するためにキャッシュされます。

モデルデータが必要なときはいつでもクロージャが呼び出されます。 Fooが正常に動作するためには、データでなければなりません。

class Foo 
{ 
    typealias ModelGetter = (() -> Model) 
    fileprivate var _modelGetter: ModelGetter! 

    ... 

    func configure(with modelGetter: @escaping ModalGetter) 
    { 
     _modelGetter = modelGetter 
    } 

    func printLastestModel() 
    { 
     // Get the latest model, do something with it. 
     precondition(_modelGetter != nil) 
     let model = _modelGetter() 
     print(model) 
    } 
} 

上記のコードでは、_modelGetterは暗黙的にアンラップされています。私はそれをOptionalと定義することができ、必要に応じてアンラップすることができますが、Fooは正しく動作するようにクロージャを設定する必要があります。

はFooのインスタンスを作成し、それを構成する:

let foo = Foo() 
foo.configure(with: { self.makeModel() }) 
foo.printLatestModel() 

しかし、これは保持のサイクルを作成します。

ので、[weak self]が使用されている、と私たちはselfのオプをチェック:

foo.configure(with: { [weak self] in 
    guard let strongSelf = self else { return **WHAT** } 
    return strongSelf.makeModel() 
}) 

問題これは、自己がnilであっても、閉鎖はまだ返す必要があることが必要です

モデル(つまり、WHAT?)をクロージャの呼び出し元(Fooインスタンス)に返します。しかし、selfはゼロであるため、渡すモデルはありません。

質問

は、誰かがこのような状況で使用するパターンをお勧めしますか? ModelGetterが有効かどうかを確認したり、モデルが有効かどうか疑問に思ったりすることは望ましくありません。 Fooの目的のために、Fooが存在すれば、必要なモデルを常に得ることができなければなりません。

Fooのニーズを再設計するだけで、モデルを調達できない可能性を考慮に入れる必要がありますか?助けていただきありがとうございます。

答えて

1

クラスがFooの所有者である場合、[weak self]の代わりに[unowned self]を設定することをお勧めします。問題を解決します。あるクラスが別のクラスの所有者であれば、問題になることはありませんが、論理が間違っていると、プロジェクトで何かを壊したというシグナルであるので、悪いことはありません。

+0

ありがとうございました。私はこのアプローチを取って、プログラマー/設計ミスとしてクラッシュを処理します。 – Womble

1

ただし、これにより保持サイクルが作成されます。

いいえ。 fooはクロージャーへの参照を所有しており、クロージャーはself(明らかにfooではない)への参照を所有しています。 Fooの強い財産がselfにあり、それをfooに設定した場合にのみ、保有サイクルが得られます。あなたはそれをやろうとしている前提で

、私は2つのパターンのいずれかを使用します。

  • 私はselfは常にfooの存続期間があるでしょう、プログラマとして仮定を作ります。その場合、[weak self]の代わりに[unowned self]を使用します。私の前提が間違っていると判明した場合、プログラムは中断し、スタックトレースに基づいてバグを修正することができます。明らかに、かなり広範なテストスイートが可能な限り仮定を検証することを望むでしょう。

    • 閉鎖オプショナルすなわち() -> Model?の戻り値の型を作るのFooが可能にする:あなたは消失を処理する方法についての3つの選択肢が持っている場合には、私はselfが消えるすることが有効であると判断した

    • nilモデル

    • selfnilの場合に返される既定値はModelです。
    • selfnilの場合、クロージャがスローすると宣言してエラーをスローします。

私はおそらく[unowned self]で行くと、私は明示的にどこかへの強い参照を保持してくださいと思います。

+0

ありがとう、ジェレミー。私はあなたのアドバイスとYerkebulan'sのアドバイスを取って、[無所属の]自己の道に行きます。乾杯。 – Womble

関連する問題