1. ホーム
  2. swift

[解決済み] Swiftではクロージャの内部では常に[unowned self]を使うべきか?

2022-03-21 18:20:31

質問

WWDC 2014のセッション403にて 中級Swift トランスクリプト そして、次のようなスライドがありました。

スピーカーは、その場合、もし私たちが [unowned self] メモリリークになります。ということは、常に [unowned self] をクロージャの中に入れてください。

オン Swift天気アプリのViewController.swiftの64行目 を使用していない。 [unowned self] . しかし、私はUIを更新するためにいくつかの @IBOutlet のように self.temperatureself.loadingIndicator . というのは、すべての @IBOutlet は、私が定義した weak . しかし、安全のために、常に [unowned self] ?

class TempNotifier {
  var onChange: (Int) -> Void = {_ in }
  var currentTemp = 72
  init() {
    onChange = { [unowned self] temp in
      self.currentTemp = temp
    }
  }
}

解決方法は?

を使いたくない場合もあるはずです。 [unowned self] . 時には、クロージャが呼ばれたときにまだ存在していることを確認するために、クロージャに self を捕捉させたいことがあります。

例 非同期ネットワークリクエストの作成

非同期ネットワークリクエストを行う場合は、以下のようになります。 する をクロージャに保持させたい。 self リクエストの終了時のためです。そのオブジェクトは他の方法で割り当て解除されたかもしれませんが、まだリクエストの終了を処理できるようにしたいのです。

を使用する場合 unowned self または weak self

を本当に使いたいのはこの時だけです。 [unowned self] または [weak self] を作成する場合です。 強い参照サイクル . 強力な参照サイクルとは、所有権のループが存在し、オブジェクトが(おそらくサードパーティを通じて)お互いを所有することになり、その結果、お互いがお互いを維持することを保証するため、決して割り当て解除されることがない状態です。

クロージャの場合、その内部で参照されるすべての変数は、クロージャによってquot;own"されることを理解すればよいのです。クロージャが存在する限り、これらのオブジェクトは存在し続けることが保証されています。この所有権を停止させる唯一の方法は [unowned self] または [weak self] . つまり、あるクラスがクロージャを所有し、そのクロージャがそのクラスへの強い参照をキャプチャしている場合、クロージャとクラスの間に強い参照のサイクルが存在することになります。これは、クラスがクロージャを所有する何かを所有する場合も含まれます。

具体的には、ビデオの例では

スライドの例では TempNotifier はクロージャを onChange メンバ変数があります。もし self として unowned を所有し、クロージャは self という強力なリファレンスサイクルを構築している。

との違い unownedweak

との違いは unownedweak は、その weak がOptionalとして宣言されているのに対し unowned はありません。これを宣言することで weak を使えば、クロージャの内部でnilになる可能性がある場合にも対処できます。もしあなたが unowned 変数がたまたまnilであった場合、プログラム全体がクラッシュします。そのため unowned クロージャが存在する間、その変数が常に存在することが確実な場合。