Swift Academy · レッスン

循環参照とweak/unownedによる解消

オブジェクト間やクロージャとの循環参照を見つけ、安全に weak 参照や unowned 参照を使って解消します。

レッスン 2/38 ステップ

「循環参照とweak/unownedによる解消」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン2/3です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全3レッスンが含まれています。

循環参照とは

循環参照は、オブジェクト(またはクロージャ)が互いにstrong参照を保持し、ARCのカウントが0にならない状態です。weakまたはunownedで循環参照を解消します。

オブジェクト同士の循環参照

両方向のstrong参照はメモリリークを作ります。どちらのオブジェクトもカウントを0まで減らせないためです。

final class Owner {
    var gadget: Gadget?
    deinit { print("Owner deinit") }
}
final class Gadget {
    var owner: Owner?
    deinit { print("Gadget deinit") }
}
// Strong ⇄ strong (cycle)
var o: Owner? = Owner()
var g: Gadget? = Gadget()
o!.gadget = g
g!.owner = o
o = nil      // no deinit
g = nil      // still no deinit (leak)

weakで解消する

片方(多くの場合、delegateやownerなどの逆方向の参照)をweakにすると、ARCによって両方を解放できるようになります。

final class Owner2 {
    var gadget: Gadget2?
    deinit { print("Owner2 deinit") }
}
final class Gadget2 {
    weak var owner: Owner2?   // weak breaks cycle; becomes nil automatically
    deinit { print("Gadget2 deinit") }
}
var o2: Owner2? = Owner2()
var g2: Gadget2? = Gadget2()
o2!.gadget = g2
g2!.owner = o2
o2 = nil     // Owner2 deinit
g2 = nil     // Gadget2 deinit

クロージャの循環参照(strong self)

クロージャはデフォルトで変数をstrongにキャプチャします。オブジェクト自身がそのクロージャも所有すると、循環参照が形成されます。

final class TimerClient {
    var tick: (() -> Void)?
    deinit { print("TimerClient deinit") }
    func start() {
        // BAD: closure strongly captures self; self keeps tick strongly
        tick = {
            print("tick from", self) // strong capture of self
        }
    }
}
var c: TimerClient? = TimerClient()
c!.start()
c = nil   // no deinit — closure holds self strongly

キャプチャリストで解消する

安全に後処理するには[weak self](オプショナル)を使います。クロージャの実行時にselfが必ず存続している場合にのみ[unowned self]を使います。

final class TimerClient2 {
    var tick: (() -> Void)?
    deinit { print("TimerClient2 deinit") }
    func start() {
        // Use [weak self] when self can go away before tick runs
        tick = { [weak self] in
            guard let self = self else { return } // safe unwrap
            print("tick from", self)
        }
        // Alternative when lifetime is guaranteed: [unowned self]
        // tick = { [unowned self] in print("tick from", self) }
    }
}
var c2: TimerClient2? = TimerClient2()
c2!.start()
c2 = nil   // deinit now prints — no cycle

チェックリスト

チェックリスト:

  • 双方向の参照がありますか? 片方(例: delegate)をweakにします。
  • 型にクロージャを保持していますか? [weak self]でキャプチャし、安全にアンラップします。
  • [unowned self]はライフタイムが保証される場合にのみ使います。そうでなければクラッシュする可能性があります。

クロージャでのweakとunowned

理解度チェック: オブジェクトが解放される可能性がある場合、どのキャプチャリストがより安全ですか?

まとめ

まとめ: オブジェクトとクロージャにある循環参照を見つけます。適切にweakまたはunownedで解消し、迷った場合はweakを優先します。

無料で開始

AI チューターと学ぶ Swift — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
122
レッスン
409

よくある質問

「循環参照とweak/unownedによる解消」レッスンは無料ですか?

はい。「循環参照とweak/unownedによる解消」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全3レッスンが含まれています。

「循環参照とweak/unownedによる解消」で何を学びますか?

オブジェクト間やクロージャとの循環参照を見つけ、安全に weak 参照や unowned 参照を使って解消します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/3です。

「循環参照とweak/unownedによる解消」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. ARCの基本:strong / weak / unowned
  2. 循環参照とweak/unownedによる解消
  3. 共有を減らすための値型
← Swift Academyに戻る