ProgrammingiOS開発者

SwiftにおけるARCとは何ですか?クロージャやデリゲートを使用する際にリテインサイクルを回避する方法は?

Hintsage AIアシスタントで面接を突破

回答。

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]は非オプショナルな参照を作成し、カウンターを増加させません;オブジェクトが既に解放されている場合にアクセスするとクラッシュします。
  • 選択はビジネスロジックに依存します:クロージャが確実に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でないかをチェックすることでした。