web-dev-qa-db-ja.com

Swift委任-デリゲートで弱いポインタを使用する場合

誰かがSwiftのデリゲートポインタに「弱い」割り当てを使用するときと使用しないときを説明できますか?

私の理解では、クラスとして定義されていないプロトコルを使用する場合、デリゲートポインターをweakに割り当てることはできません。

protocol MyStructProtocol{
    //whatever
}

struct MyStruct {
    var delegate: MyStructProtocol?
}

ただし、プロトコルがクラス型プロトコルとして定義されている場合、デリゲートを弱いポインターに設定しますか?

protocol MyClassProtocol:Class{
    //whatever
}

class MyClass {
    weak var delegate: MyClassProtocol?
}

私は正しいですか? AppleのSwiftガイドでは、クラスプロトコルの例は弱い割り当てを使用していませんが、私のテストでは、デリゲートが弱く参照されていない場合、強い参照サイクルが見られます。

41
nwales

通常、クラスプロトコル(classキーワードで定義)を弱くして、 "強い参照サイクル"(以前は "保持サイクル"と呼ばれていました)のリスクを回避します。デリゲートを弱くしないということは、本質的に強い参照サイクルがあることを意味するのではなく、単にcouldを持っていることを意味します。

ただし、struct型はstruct型が「参照」型ではないため、強い参照サイクルのリスクが大幅に減少します。したがって、強い参照サイクルを作成することは困難です。ただし、デリゲートオブジェクトがクラスオブジェクトである場合、プロトコルをクラスプロトコルにして弱くすることができます。

私の意見では、クラスデリゲートを弱くすることは、強い参照サイクルのリスクを部分的に軽減することです。それは本当に「所有権」の問題です。ほとんどのデリゲートプロトコルは、問題のオブジェクトがデリゲートの所有権を主張するビジネスを持たない状況ですが、問題のオブジェクトがデリゲートに何かを通知する(または何かを要求する)機能を提供しているだけです。

42
Rob

デリゲートは(編集:一般に)常に弱者でなければなりません。

baのデリゲートであるとしましょう。 adelegateプロパティはbになりました。

bがなくなったときにcを解放したい場合

cbおよびcへの強い参照を保持している場合、bcで割り当て解除する必要があります。ただし、aで強力なデリゲートプロパティを使用すると、baを強く保持しているため、bは割り当て解除されません。弱参照を使用すると、bcから強参照を失うとすぐに、bが解放されると、cは解放されます。

通常、これは意図された動作であるため、weakプロパティを使用する必要があります。

7
Schemetrical