[Swift] guard let self = self else { return } って何？


##じょ
某所で好評を得ているのでこちらに転載します。


## これはなに？

以下のようなよくあるサンプルコードの`guard let self = self else { return }`が何のためにあるのかよくわからない、という疑問にお答えします。

```swift
func didTapSignUpButton() {
    Auth.auth().createUser(withEmail: email, password: password) { [weak self] result, error in
        guard let self = self else { return }
        if let user = result?.user {
            // do something
        }
    }
}
```

## 短い回答
`[weak self]` でキャプチャした`self`がクロージャ実行時に存在しているかどうかを確認しています。

## 長い回答

### guard let else
まず、

```swift
guard let xxx = yyy else { return }
```
は`yyy`がOptionalで、`yyy`に値がなければreturnして値があれば`xxx`にその値を入れる、という構文です。

例えば以下のように動きます。

```swift
func hoge(_ value: Int?) {
   gurad let v = value else { return }
   print(v)
}

hoge(10)  // prints 10
hoge(nil) // no prints
```

###変数のキャプチャ
次に、関数による変数のキャプチャというものがあります。

```swift
var val = 0

func fuga() {
   val += 2   //  valをキャプチャ
}

print(val)  // prints 0.

fuga()
print(val)  // prints 2.
```

関数にキャプチャされた変数valは関数内で値を変更することが可能です。


Swiftでは関数とクロージャは同等のものですので以下でも同じです。

```swift
var val = 0

let fuga = { val += 2 }
```

###インスタンスのオーナーシップ
最後にクラスのインスタンスのオーナーシップです。
クラスのインスタンスにはデータ領域がありますので、そのインスタンスを使わなくなった時にその領域が解放されなければメモリがひっ迫してしまいます。
しかし、使用中に開放されてしまうと、アプリケーションがクラッシュする事態になります。
このためSwiftではインスタンスにオーナーシップというものを設定しこれに対処しています。
原則として、使用中はオーナーを設定し使用が終わるとそれを外します。オーナーがすべてなくなった段階でインスタンスは解放されます。
これらは自動的に行われており、通常はプログラマは何も考える必要もありません。

ただし、循環参照という状態になるとインスタンスが解放されなくなるため、これを対処する必要があります。

```swift
class A {
  let b: B
  
  init(b: B) {
    self.b = b
    b.a = self
  }
}

class B {
   var a: A?
}

let a: A? = A(b: B())
```

この例は意味のあるコードではありませんが、循環参照の典型的な例です。
class Aのインスタンスはclass Bのインスタンスを、class Bのインスタンスはclass Aのインスタンスを参照しています。
そのため、上の例で`a = nil`としても`a`, `b`どちらのオーナーもなくならないため、どちらも解放されません。

この循環参照を回避するために`weak`という修飾子が用意されています。
上の例ではclass Bの変数`a`を`weak`とします。

```swift
class B {
   weak var a: A?
}
```
この`weak`という修飾子は「インスタンスは参照するがオーナーとしては登録するな。またインスタンスが解放されたとき値を`nil`にせよ。」という指示を与えます。
似た修飾子に`unowned`というものがあります。最後に少し説明をします。

こうすることで`a = nil`が実行されると、`a`のオーナーがすべてなくなり`a`が解放され、それによって`b`のオーナーもなくなるため`b`も解放されるようになります。

###キャプチャによるオーナシップの獲得
まだまだ続きます。

つぎは今までできたことの複合技、キャプチャによるオーナシップの獲得です。

これは名前の通りです。先ほどのclass Aを使います。

```swift
var a: A? = A(b: B())

let f = { print(a) }  // インスタンスaをキャプチャ

a = nil // インスタンスaは解放されない
```
クロージャがインスタンスaをキャプチャした時、自動的にオーナーが設定されるため、`a = nil`を実行してもインスタンスaは解放されません。ただしこの場合は、`f`が使われなくなった時に`f`と一緒に`a`も解放されます。

これにも循環参照の問題が発生します。

```swift
class C {
  var f: (() -> Void)?
}

let c: C? = C()

c?.f = { print(c) }

c = nil  // c は解放されない
```
このようにインスタンス`c`が持つクロージャがcをキャプチャしてしまったため、循環参照が発生し、`c`が解放されなくなってしまいます。
この時も`weak`修飾子を使います。ただし、クロージャ自体をweak参照することができないため以下のように行います。

```swift
c?.f = { [weak c] in print(c) }
```
この`weak`は`c`をキャプチャする時にオーナーを設定するなという指示になります。
この指定をすることで`c = nil`の時にインスタンス`c`が解放されるようになります。

ところが、これでも問題が発生する場合があります。class Aを使います。

```swift
var a: A? = A(b: B())

let f = { [weak a] in print(a) }

a = nil

f()  // prints nil
```
`a`が解放された後にクロージャfを実行しようとすると、クロージャ内で使用している`a`がすでに存在していないため`nil`になってしまいます。

###キャプチャしたインスタンスの存在確認

この問題を解決するためには実行前にインスタンス`a`が存在することを確認する必要があります。
クロージャ`f`を以下のようにします。

```swift
let f = { [weak a] in
    gurad let a = a else { return }
    print(a)
}
```
まず、`gurad let a = a else { return }`でインスタンス`a`の存在を確認し、その後それを使用するようにします。

冒頭のサンプルコードにある`guard let self = self else { return }`も同じことです。
`[weak self]`でキャプチャした`self`がクロージャ実行時に存在しているかどうかを確認しています。

##おまけ

### キャプチャ時の`weak`指定の副作用
すっかりだまされいるようですね。
書いてあることは正しいのですが、実は`guard let self = self else { return }`についての説明が足りてません。

>
```swift
guard let xxx = yyy else { return }
```
は`yyy`がOptionalで、`yyy`に値がなければreturnして値があれば`xxx`にその値を入れる、という構文です。

と書きましたが、`guard let self = self else { return }`の右の`self`はOptional型ではないはずです。

ところが、

```swift
var a: A? = A(b: B())

let f = { [weak a] in print(a) }
```
これを

```swift
let a = A(b: B())

let f = { [weak a] in print(a) }
```
としたとしても、クロージャ内の`a`は`A`型ではなく`Optional<A>`型になります。
これがキャプチャ時の`weak`指定の副作用です。
`weak`は「（略）解放されたとき値を`nil`にせよ」という指示なのでOptional型じゃないと無理なんです。
なので強制的に`Optional`型になります。

### unowned
「循環参照を避けたいけど、`weak`だと`Optional`になって面倒くさい！ ここでは絶対インスタンスは存在してるのに！！！」
という時に使うのが`unowned`です。

`weak`修飾子は「インスタンスは参照するがオーナーとしては登録するな。またインスタンスが解放されたとき値を`nil`にせよ。」という指示でしたが、`unowned`は「インスタンスは参照するがオーナーとしては登録するな」だけの指示を与えます。
`nil`にする必要がないため、キャプチャ時に強制的に`Optional`型になることはありません。
アンラップを使うことなくそのまま利用できますので便利です。

ただし、当然のことながら`unowned`はオーナーを設定しないため利用しようとしたときにインスタンスが解放されてしまっていることがあります。
解放されたインスタンスにアクセスするとプログラムがクラッシュします。
`unowned`を使う場合はそのことに十分注意しましょう。