ARC(自動参照カウント)とは、Swiftにおけるメモリ管理のシステムです。オブジェクトへの新しい強い参照が作成されるたびにカウンターが増加し、削除されると減少します。カウンターがゼロになるとオブジェクトは解放されます。
リテインサイクル(保持サイクル)とは、オブジェクト同士が強い参照で相互に参照し合い、決して解放されない状況を指します。
回避方法:
protocol SomeDelegate: AnyObject { } class Owner { weak var delegate: SomeDelegate? }
[weak self]または[unowned self]を使用します:class Example { var closure: (() -> Void)? func setup() { closure = { [weak self] in self?.doSomething() } } func doSomething() { } }
クロージャ内の[weak self]と[unowned self]の違いは何ですか?どのタイプの参照を使用すべきで、いつ使うべきですか?
回答:
[weak self]はオプショナルな参照を作成します;selfはnilになる可能性があるため、通常は安全にself?をアンラップします。[unowned self]は非オプショナルな参照を作成し、カウンターを増加させません;オブジェクトが既に解放されている場合にアクセスするとクラッシュします。[unowned self]を使用できます。例:
someClosure = { [weak self] in self?.doTask() } // または(selfが100%クロージャより長く生存する場合): someClosure = { [unowned self] in doTask() }
ストーリー
プロジェクト内でViewControllerとそのボタン処理に関連付けられたクロージャの間にリテインサイクルが発生しました。ViewControllerはクロージャを参照しており、そのクロージャはselfを強い参照で捕捉していました。その結果、コントローラーとそのすべてのデータは画面を閉じても解放されませんでした。問題は、クロージャ内で[weak self]を導入することで解決されました。
ストーリー
2つのオブジェクト間のデリゲートパターンの実装。デリゲートは強い(
strong)プロパティとして宣言されていました。その結果、主要なオブジェクトをメモリから削除しようとすると、デアロケーションされず、メモリリークが発生しました。デリゲートをweakに変更したことで問題は解決されました。
ストーリー
アニメーションにUIView内のクロージャが使用されていました。クロージャは
[unowned self]を使用してselfをキャプチャしていました。ビューがアニメーションの完了前に削除されると、すでに解放されたselfにアクセスしようとしたため、アプリケーションがクラッシュしました。解決策は、[weak self]を使用し、クロージャ内でselfがnilでないかをチェックすることでした。