スウィフトは:
- 強い参照
- 弱い参照
- 所有されていない参照
所有されていない参照と弱い参照との違いは何ですか?
所有されていない参照を使用しても安全ですか?
所有されていない参照は、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ができないと確信しているときに使用してください。nilself
例(もちろん、ターゲットをから直接追加できますが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がある場合にご利用ください。nilself
例:
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を使用することは、あなたとあなたのコードの読者を混乱させるだけです。