キャプチャリストによる値の固定は、オブジェクトの深いコピーではありません。整数なら生成時の値を保ち、クラス参照なら同じオブジェクトを指し続けます。weakは対象を生存させない別の所有権選択です。
仕組みと設計の判断基準
変更可能なローカル変数をキャプチャしたクロージャは、後の変更を観察できます。[number]のようなリストは生成時の値を保持します。引数のクロージャを戻り後も使えるよう保存するなら@escapingが必要ですが、非同期実行やリークを意味するわけではありません。 一次資料
再現コード
同じ関数内で通常のキャプチャと数値のスナップショットを作り、numberを2に変えます。次にクラス参照をキャプチャして値を3に変え、weakの対象は解放します。Queueはコールバックを保存し、一度実行して消去します。
この独立したサンプルは2026-10-23に、arm64 macOS向けのApple Swift 6.4をSwift 6言語モードで実行しました。ネットワーク接続や追加パッケージは不要です。
ダウンロード先のフォルダーで実行してください。検証条件を満たさない場合はpreconditionで停止します。検証が削除されるため、-Ouncheckedは使用しないでください。
swift -swift-version 6 swift-closure-capture-weak-self-escaping.swift
final class Box { var value = 1 }
final class Queue {
private var action: (() -> Int)?
func enqueue(_ action: @escaping () -> Int) { self.action = action }
func run() -> Int? {
let current = action
action = nil
return current?()
}
}
func experiment() {
var number = 1
let live = { number }
let snapshot = { [number] in number }
number = 2
precondition(live() == 2 && snapshot() == 1)
let box = Box()
let capturedReference = { [box] in box.value }
box.value = 3
precondition(capturedReference() == 3)
var temporary: Box? = Box()
let weakRead = { [weak box = temporary] in box?.value }
precondition(weakRead() == 1)
temporary = nil
precondition(weakRead() == nil)
let queue = Queue()
queue.enqueue(snapshot)
precondition(queue.run() == 1 && queue.run() == nil)
print("variable=2 snapshot=1 captured-object=3 weak-after-release=nil queued=1 then=nil")
}
experiment()
実行結果と読み取り方
variable=2 snapshot=1 captured-object=3 weak-after-release=nil queued=1 then=nil
通常のキャプチャは2、数値のスナップショットは1、オブジェクト参照は変更後の3を返しました。weakは解放後にnilを返します。Queueは最初に1、次にnilです。このQueueは同期的な保存例で、非同期スケジューラーではありません。
適用範囲と注意点
キャプチャが必ずヒープ割り当てを起こすとは限りません。コンパイラーは保存方法を最適化できます。[weak self]を一律に付けず、所有者の消滅後に処理を省略してよいか判断してください。循環の確認には直接・間接の所有経路を調べます。
次に確認すること
保存するコールバックの所有者、消去時点、キャンセル時の意味を明記します。処理が所有者の生存を必要とするなら、機械的に弱参照へ変えないでください。実際の所有循環の切断はARC実験で確認できます。
出典と確認基準
- The Swift Programming Language: ClosuresSwift.org · 公式ドキュメント · 確認日 2026年10月23日根拠: 実装の契約と説明の根拠です。出力は、この記事に掲載した実験で別途確認しました。

