[解決済み] 弱い自分はどこへ行くのか?
質問
よくこんなことをします。
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
beep()
}
とあるアプリでは、よくこんなことをやっています。
tickle.fresh(){
msg in
paint()
}
が、もし これ
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
tickle.fresh(){
msg in
paint()
}
}
を行う必要があります。 これ
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in
tickle.fresh(){
msg in
self?.paint()
}
}
または、もしかしたら これ
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) {
tickle.fresh(){
[weak self] msg in
self?.paint()
}
}
あるいは、これ
let when = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: when) { [weak self] _ in
tickle.fresh(){
[weak self] msg in
self?.paint()
}
}
どうすればいい?
3つの提案のすべて と思われる は完璧に機能するように見えます。ここでの意味の完全な深さは何なのでしょうか?そして、どちらを行うべきでしょうか?弱い参照への強い参照は、弱い参照なのか強い参照なのか?To be か not to be か? それが問題だ!
どのように解決する?
まず第一に、一般に、retain cyclesについて心配する必要がないことに注意してください。
DispatchQueue.main.asyncAfter
でクロージャが実行されるからです。
いくつかの
点で実行されるからです。したがって、弱く捕捉するかどうかに関わらず
self
を弱く捕捉しようがしまいが、永久に保持するサイクルは作らない(と仮定して
tickle.fresh
もそうでないと仮定します)。
を付けるかどうかは別として
[weak self]
キャプチャリストを外側の
asyncAfter
クロージャが必要かどうかで決まります。
self
をクロージャが呼ばれるまで(設定された時間の後)保持したいかどうかによります。もし
self
がクロージャが呼ばれるまで生きている必要があるならば、 クロージャに
[weak self]
を入れるか、そうであれば入れないか。
を入れるかどうかは
[weak self]
をつけるかどうか、また、内側のクロージャ(
tickle.fresh
を外側のクロージャで捕捉しているかどうかに依存します。もしそうでないなら、外側のクロージャに
self
を置くことで、内側のクロージャがそれを保持しないようにします。しかし、もし外側のクロージャがすでに弱く捕捉していれば
[weak self]
を捕捉していた場合、内側のクロージャーは
すでに
への弱い参照を持っています。
self
への参照は弱いので
self
を追加しても効果はありません。
というわけで、まとめると
[weak self]
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { msg in
self.paint()
}
}
は外側と内側の両方のクロージャによって保持されます。
self
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { msg in
self?.paint()
}
}
はどちらのクロージャでも保持されません。
self
上記と同様に、追加の
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
tickle.fresh { [weak self] msg in
self?.paint()
}
}
を追加しても効果はありません。
[weak self]
はすでに外側のクロージャによって弱く捕捉されているため、効果はありません。
self
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
tickle.fresh { [weak self] msg in
self?.paint()
}
}
は外側クロージャで保持されますが、内側クロージャでは保持されません。
もちろん、あなたが必要としないかもしれない
self
を外側のクロージャに保持させたくないが
を行う
は内側のクロージャに保持させたい。このような場合、外側のクロージャでローカル変数を宣言することで
self
への強い参照を保持するために、外側のクロージャでローカル変数を宣言し、内側のクロージャでキャプチャすることができます。
self
今すぐ
DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
guard let strongSelf = self else { return }
tickle.fresh { msg in
strongSelf.paint()
}
}
は外側のクロージャによって生かされることはありませんが、いったん呼び出されると
self
がまだ存在していれば、内側のクロージャによって、そのクロージャが解放されるまで生かされます。
に対応しています。
<ブロッククオート弱い参照への強い参照は、弱い参照と強い参照のどちらでしょうか?
弱参照は、値型であるoptionalとして実装されています。そのため、以下のようなことはできません。
を直接
その代わりに、まずそれをアンラップし、基礎となるインスタンスへの強い参照を取らなければなりません。この場合、単に強い参照を扱っているに過ぎません。
self
).
ただし、弱参照が ボックス化 (これはクロージャ キャプチャで発生します。値の型はヒープで割り当てられたボックスに入れられます) - そのボックスへの強い参照を実際に持つことができます。この効果は、元のインスタンスへの弱い参照と同等であり、目に見えない追加の間接的なビットを持つだけです。
実際、これは
まさに
のように、外側のクロージャが弱く捕捉する例で起こることです。
strongSelf
であり、内側のクロージャはその弱い参照を「強く捕捉」している。その結果、どちらのクロージャーも
self
.
関連
-
[解決済み] JavaにおけるSoftReferenceとWeakReferenceの違いは何ですか?
-
[解決済み] 純粋な」Swift で弱いプロトコル参照を作るには (@objc なしで) どうしたらいいですか?
-
[解決済み】weak referenceとunowned referenceの違いは何ですか?
-
[解決済み】ARCでブロックに自己の弱参照を必ず渡す?
-
[解決済み] 非'@objc'メソッドは'@objc'プロトコルのオプション要件を満たしていない
-
[解決済み] Swift - サブクラスでオーバーライドする必要があるクラスメソッド
-
[解決済み] SwiftUIでビューを動的に隠す
-
[解決済み] Xcode playgrounds が Sources フォルダにある swift ファイルにアクセスできない。
-
[解決済み] Swiftの定数。構造体か列挙型か
-
[解決済み] iOS 9のスワイプ可能なテーブルビューセル
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] Swift 3でカスタム通知を作成するには?
-
[解決済み] Swift 1.2では、宣言は「final」と「dynamic」の両方にはなり得ないというエラーがある
-
[解決済み] Swiftで範囲を作成する方法は?
-
[解決済み] ビルド入力ファイルが見つかりません」Swift 4.2、Xcode 10.0
-
[解決済み] ボタンを無効化する
-
[解決済み] Swiftでenumの関連値を無視して比較する方法は?
-
[解決済み] SHA256 in swift
-
[解決済み] SwiftUIのDSLを可能にするものは何ですか?
-
[解決済み] Swiftでオプショナルをダウンキャストする:as? タイプ、または as! タイプ?
-
[解決済み] SceneDelegateとAppDelegateの違いについて