スウィフトは:
- 強い参照
- 弱い参照
- 所有されていない参照
所有されていない参照と弱い参照との違いは何ですか?
所有されていない参照を使用しても安全ですか?
所有されていない参照は、C / C ++のダングリングポインターのようなセキュリティリスクですか?
unowned
たちが制御するクラス、Appleクラスの場合に使用するweak
ことです。それが何をするかを確実に保証することはできないためです
スウィフトは:
所有されていない参照と弱い参照との違いは何ですか?
所有されていない参照を使用しても安全ですか?
所有されていない参照は、C / C ++のダングリングポインターのようなセキュリティリスクですか?
unowned
たちが制御するクラス、Appleクラスの場合に使用するweak
ことです。それが何をするかを確実に保証することはできないためです
回答:
weak
とunowned
参照はどちらも、参照さ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
例を示すゼロであることが許可されている両方が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にならないという3番目のシナリオもあります。
また、クロージャを操作する際に回避する古典的な保持サイクルのシナリオもあります。
これについては、Appleのドキュメントにアクセスするか、本を読むことをお勧めします。
weak var Person?
対はvar Person?
?
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 ++の「ダングリングポインター」のようなセキュリティリスクを参照していますか
そうは思いません。
所有されていない参照は、値を持つことが保証されている単なる弱い参照であるため、決してセキュリティリスクになることはありません。ただし、参照されているインスタンスの割り当てが解除された後で、所有されていない参照にアクセスしようとすると、ランタイムエラーがトリガーされ、アプリがクラッシュします。
それは私がそれで見る唯一のリスクです。
unowned
は、子クラスの親のプロパティに使用します。弱いとは逆です。素晴らしい説明@myxtic! unowned
参照はweak
、値を持つことが保証されている単なる参照です!
クロージャでセルフがnilの場合は、[weak self]を使用します。
クロージャーで自分自身がnilにならない場合は、[unowned self]を使用します。
[unowned self]を使用するとクラッシュする場合、そのクロージャーのある時点でおそらくselfはnilであり、代わりに[weak self]を使用する必要があります。
クロージャーでstrong、weak、およびunownedを使用する例を確認してください。
self
ようにしてnil にすることができますか?
リンクからの抜粋
いくつかの結論点
weak
とunowned
参照の両方がオブジェクトの参照カウントに影響を与えることはありません。ただし、弱参照は常にオプションになります。つまり、nilにすることができますが、unowned
参照をnilにすることはできません。オプションの参照を使用する場合、オブジェクトがnilになる可能性を常に処理する必要があります。所有されていない参照の場合は、オブジェクトがnilにならないようにする必要があります。nilオブジェクトへの所有されていない参照を使用することは、nilであるオプションを強制的にアンラップすることに似ています。
つまり、オブジェクトのライフタイムが参照よりも長いことが確実な場合は、所有されていない参照を使用しても安全です。そうでない場合は、代わりに弱い参照を使用することをお勧めします。
質問の3番目の部分については、所有されていない参照がぶら下がりポインタに似ているとは思いません。参照カウントについて話すとき、通常はオブジェクトの強い参照カウントを指します。同様に、swiftはオブジェクトの所有されていない参照カウントと弱い参照カウントを維持します(弱い参照は、オブジェクト自体ではなく、「サイドテーブル」と呼ばれるものを指します)。強い参照カウントがゼロに達すると、オブジェクトは初期化解除されますが、所有されていない参照カウントがゼロより大きい場合は、割り当てを解除できません。
ここで、ダングリングポインターは、既に割り当て解除されているメモリの場所を指すものです。ただし、オブジェクトへの所有されていない参照がある場合に限り、メモリの割り当てを解除できるので、すぐに宙ぶらりんのポインタが発生することはありません。
迅速なメモリ管理について詳しく説明している記事はたくさんあります。こちらです。
所有されていない参照は、2つのオブジェクト間のSame-Lifetime関係の場合に使用される一種の弱い参照であり、オブジェクトは常に他の1つのオブジェクトによってのみ所有されるべきです。これは、オブジェクトとそのプロパティの1つとの間に不変のバインディングを作成する方法です。
中間の迅速なWWDCビデオで示されている例では、人はクレジットカードを所有しており、クレジットカードは1人の所有者しか持てません。クレジットカードでは、所有者が1人だけのクレジットカードを持ち歩きたくないので、その人はオプションのプロパティにしないでください。クレジットのホルダープロパティを弱い参照にすることで、このサイクルを壊すことができますが、それを(定数ではなく)変数だけでなくオプションにすることも必要です。この場合の所有されていない参照とは、CreditCardがPersonに所有権を持たないが、その寿命はそれに依存することを意味します。
class Person {
var card: CreditCard?
}
class CreditCard {
unowned let holder: Person
init (holder: Person) {
self.holder = holder
}
}
unowned
あなたがその時点でアクセスするポイントに決していることself
ができないと確信しているときに使用してください。nil
self
例(もちろん、ターゲットをから直接追加できますがMyViewController
、これも簡単な例です):
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myButton = MyButton { [unowned self] in
print("At this point, self can NEVER be nil. You are safe to use unowned.")
print("This is because myButton can not be referenced without/outside this instance (myViewController)")
}
}
}
class MyButton: UIButton {
var clicked: (() -> ())
init(clicked: (() -> ())) {
self.clicked = clicked
// We use constraints to layout the view. We don't explicitly set the frame.
super.init(frame: .zero)
addTarget(self, action: #selector(clicked), for: .touchUpInside)
}
@objc private func sendClosure() {
clicked()
}
}
アクセスするweak
可能性self
がある場合にご利用ください。nil
self
例:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NetworkManager.sharedInstance.receivedData = { [weak self] (data) in
print("Can you guarentee that self is always available when the network manager received data?")
print("Nope, you can't. Network manager will be alive, regardless of this particular instance of MyViewController")
print("You should use weak self here, since you are not sure if this instance is still alive for every")
print("future callback of network manager")
}
}
}
class NetworkManager {
static let sharedInstance = NetworkManager()
var receivedData: ((Data) -> ())?
private func process(_ data: Data) {
// process the data...
// ... eventually notify a possible listener.
receivedData?(data)
}
}
の短所unowned
:
の短所weak
:
不明な場合は、を使用してくださいweak
。待って、私はここであなたのケースで何をすべきかをStackOverflowでここに尋ねることを意味する!使用すべきでないときにいつもweakを使用することは、あなたとあなたのコードの読者を混乱させるだけです。