262

スウィフトには次のものがあります。

  • 強力な参照
  • 弱参照
  • 所有されていない参照

非所有参照と弱参照の違いは?

所有されていない参照を安全に使用できるのはいつですか?

所有されていない参照は、C/C++のダングリング ポインターのようなセキュリティ リスクですか?

4

7 に答える 7

380

との両方weakunowned参照は、参照されたオブジェクトに保持を作成しませんstrong(別名、ARC が参照されたオブジェクトの割り当てを解除するのを防ぐために、保持カウントを増やしません)。

しかし、なぜ 2 つのキーワードを使用するのでしょうか。この違いは、Optional型が Swift 言語に組み込まれているという事実に関係しています。それらについての簡単な話:オプションの型はメモリの安全性を提供します (これは、この利点を提供するために厳密なSwift のコンストラクター規則で美しく機能します)。

weak参照により、それが可能になる可能性がありますnil(これは、参照されたオブジェクトの割り当てが解除されると自動的に発生します)。したがって、プロパティの型はオプションでなければなりません。コンパイラは、できる限り安全なコードを書くように強制します)。

参照は、その存続期間中unownedは決してならないことを前提としていますnil。所有されていない参照は、初期化中に設定する必要があります。これは、参照が、チェックなしで安全に使用できる非オプションの型として定義されることを意味します。参照されているオブジェクトの割り当てが解除された場合、所有されていない参照が使用されるとアプリがクラッシュします。

アップルのドキュメントから:

弱参照は、その参照が存続期間中のある時点で nil になることが有効な場合はいつでも使用してください。逆に、初期化中に設定された参照が nil にならないことがわかっている場合は、所有されていない参照を使用します。

ドキュメントには、保持サイクルとその解除方法について説明している例がいくつかあります。これらの例はすべてdocs から抜粋したものです。

weakキーワードの例:

class Person {
    let name: String
    init(name: String) { self.name = name }
    var apartment: Apartment?
}
 
class Apartment {
    let number: Int
    init(number: Int) { self.number = number }
    weak var tenant: Person?
}

そして今、いくつかのASCIIアートについて(ドキュメントを見に行くべきです- 彼らはかなりの図を持っています):

Person ===(strong)==> Apartment
Person <==(weak)===== Apartment

PersonとのApartment例は、どちらも nil が許可されている 2 つのプロパティが強い参照サイクルを引き起こす可能性がある状況を示しています。このシナリオは、弱参照で解決するのが最適です。両方のエンティティは、他方に厳密に依存することなく存在できます。

unownedキーワードの例:

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) { self.name = name }
}
 
class CreditCard {
    let number: UInt64
    unowned let customer: Customer
    init(number: UInt64, customer: Customer) { self.number = number; self.customer = customer }
}

この例では、 にCustomerがある場合とない場合がありますCreditCardが、CreditCard は常にに関連付けられCustomerます。これを表すために、Customerクラスにはオプションのcardプロパティがありますが、CreditCardクラスにはオプションではない (所有されていない)customerプロパティがあります。

Customer ===(strong)==> CreditCard
Customer <==(unowned)== CreditCard

CustomerとのCreditCard例は、nil が許可されている 1 つのプロパティと、nil にできない別のプロパティが強い参照サイクルを引き起こす可能性がある状況を示しています。このシナリオは、所有されていない参照で解決するのが最適です。

Apple からのメモ:

弱参照は変数として宣言して、その値が実行時に変更される可能性があることを示す必要があります。弱参照は定数として宣言できません。

両方のプロパティが常に値を持つ必要があり、初期化が完了したらどちらのプロパティも決して nil にしないという 3 番目のシナリオもあります。

また、クロージャーを操作するときに避けるべき、従来のリテイン サイクル シナリオもあります。

これについては、 Apple のドキュメントにアクセスするか、本を読むことをお勧めします。

于 2014-09-24T19:43:09.863 に答える
36

Q1. 「非所有参照」と「弱い参照」の違いは何ですか?

弱参照:

弱参照とは、参照先のインスタンスを強力に保持しない参照であるため、ARC が参照先のインスタンスを破棄するのを止めません。弱参照には「値なし」が許可されているため、すべての弱参照をオプションの型として宣言する必要があります。(アップルのドキュメント)

未所有の参照:

弱い参照と同様に、所有されていない参照は、それが参照するインスタンスを強力に保持しません。ただし、弱い参照とは異なり、所有されていない参照は常に値を持つと見なされます。このため、所有されていない参照は常に非オプションの型として定義されます。(アップルのドキュメント)

それぞれをいつ使用するか:

弱参照は、その参照が存続期間中のある時点で nil になることが有効な場合はいつでも使用してください。逆に、初期化中に設定された参照が nil にならないことがわかっている場合は、所有されていない参照を使用します。(アップルのドキュメント)


Q2. 「所有されていない参照」を安全に使用できるのはいつですか?

上で引用したように、所有されていない参照は常に値を持つと想定されます。したがって、参照が決して nil にならないことが確実な場合にのみ使用してください。Apple Docs は、次の例を通じて、所有されていない参照の使用例を示しています。

と の 2 つのクラスがあるCustomerとしCreditCardます。顧客はクレジット カードがなくても存在できますが、顧客がいなければクレジット カードは存在しません。つまり、クレジット カードには常に顧客がいると想定できます。したがって、それらは次の関係を持つ必要があります。

class Customer {
    var card: CreditCard?
}

class CreditCard {
    unowned let customer: Customer
}

Q3. 「所有されていない参照」は、C/C++ の「ダングリング ポインター」のようなセキュリティ リスクを参照しますか?

私はそうは思わない。

所有されていない参照は、値を持つことが保証されている単なる弱い参照であるため、セキュリティ リスクになることはありません。ただし、参照するインスタンスの割り当てが解除された後に、所有されていない参照にアクセスしようとすると、ランタイム エラーが発生し、アプリがクラッシュします。

それが私が見た唯一のリスクです。

Apple ドキュメントへのリンク

于 2014-10-21T17:47:23.057 に答える
26

クロージャでselfが nil になる可能性がある場合は、 [weak self]を使用します。

クロージャでselfが決して nil にならない場合は、 [unowned self]を使用します。

[unowned self]を使用したときにクラッシュする場合は、おそらくそのクロージャのある時点で self が nil であり、代わりに[weak self]を使用する必要があります。

クロージャーでのstrongweak、およびunownedの使用例を確認してください。

https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html

于 2014-10-27T23:37:33.463 に答える
6

リンクから抜粋

いくつかの結論

  • 強い、弱い、または所有されていないことを心配する必要があるかどうかを判断するには、「私は参照型を扱っていますか」と尋ねます。Structs または Enums を使用している場合、ARC はそれらの型のメモリを管理していないため、これらの定数または変数に weak または unowned を指定することについて心配する必要さえありません。
  • 強い参照は、親が子を参照する階層関係では問題ありませんが、その逆は問題ありません。実際、ほとんどの場合、強参照は最も適切な種類の参照です。
  • 2 つのインスタンスが必要に応じて相互に関連している場合は、それらのインスタンスの 1 つが他のインスタンスへの弱参照を保持していることを確認してください。
  • 2 つのインスタンスが、一方のインスタンスが他方のインスタンスなしでは存在できないような方法で関連付けられている場合、必須の依存関係を持つインスタンスは、もう一方のインスタンスへの非所有参照を保持する必要があります。
于 2015-05-21T16:38:57.757 に答える
0

所有されていない参照は、オブジェクトが他の 1 つのオブジェクトによってのみ所有されるべきである場合に、2 つのオブジェクト間の Same-Lifetime 関係の場合に使用される一種の弱い参照です。これは、オブジェクトとそのプロパティの 1 つとの間に不変のバインディングを作成する方法です。

中間の迅速な WWDC ビデオで示されている例では、個人がクレジット カードを所有しており、クレジット カードには 1 つの所有者しか存在できません。クレジット カードでは、所有者が 1 人しかいないクレジット カードを持ちたくないため、個人を任意のプロパティにすることはできません。クレジットの所有者プロパティを弱参照にすることで、このサイクルを断ち切ることができますが、それには、(定数ではなく) 変数だけでなく、オプションにする必要もあります。この場合の所有されていない参照は、CreditCard が Person を所有していないが、その寿命はそれに依存していることを意味します。

class Person {
    var card: CreditCard?
}

class CreditCard {

    unowned let holder: Person

    init (holder: Person) {
        self.holder = holder
    }
}
于 2014-06-06T19:35:29.970 に答える