【Swift】Optional型を安全に扱う5つの方法

# Optional型とは

nilを代入できる型のこと。

```swift
let a: Int? = Int("42") // Optionalで宣言
let b: Optional<Int> = Int("42") // 上と同義
```

ただし他の型の変数に代入したりする場合、unwrapという処理が必要になる。
その際、nilが代入されている可能性があるので慎重に扱わなければなりません。
ここではOptional型を安全にunwrapして扱うための5つの方法をまとめました。

# 1. Force Unwrapping
変数の中身がなんであれとにかくunwrapする。
もしnilだった場合はruntime errorとなってしまうため、nilでないことが確かな場合に使うと良い。
"Unconditional Unwrapping"とも言うらしい。

```swift
let myOptioal: String? // Optional<String>で宣言
myOptional = "Angela" // 文字列を代入
print(myOptional!) // "Angela"が出力される
```

```swift
let myOptioal: String? // Optional<String>で宣言
myOptional = nil // nilを代入
print(myOptional!) // runtime errorとなる
```

# 2. Check for nil value
if statementでunwrapしようとしている変数の中身がnilかどうか判定し、trueの場合の処理でunwrapをする。

```swift
let myOptioal: String? // Optional<String>で宣言
myOptional = nil // nilを代入

if myOptional != nil {
  print(myOptional!) // nilでない場合のみunwrapするので安全
} else {
  print("myOptional was found to be nil") // nilだった場合はこちらの処理が実行される
}
```

unwrapする前にnilかどうか判定するので安全な一方で、毎回unwrapしなくてはならないので面倒。そんなときは次の"Optional Binding"が有効。

```swift
let myOptioal: String? // Optional<String>で宣言
myOptional = nil // nilを代入

if myOptional != nil {
  let text1: String = myOptional!
  let text2: String = myOptional!
  let text3: String = myOptional! // 毎回unwrapする必要がある
} else {
  print("myOptional was found to be nil")
}
```
# 3. Optional Binding
if statementで新たな定数にOptional型の変数を代入する。nilでない場合は`if let safeOptional = myOptional`の判定はtrueになり、nilの場合は判定の結果がfalseになる。ブロックの中では非OptionalのString型である`safeOptional`が使えるのでunwrapは不要となるので便利。

```swift
let myOptioal: String? // Optional<String>で宣言
myOptional = nil // nilを代入

if let safeOptional = myOptional { 
  // myOptionalがnilでない場合はtrueになりここの処理が実行される
  let text1: String = safeOptional
  let text2: String = safeOptional
  let text3: String = safeOptional //条件の箇所で宣言したsafeOptionalは非OptionalのStringなのでunwrapは不要
} else {
  // myOptionalがnilの場合はfalseになりここの処理が実行される
  print("myOptional was found to be nil")
}
```

# 4. Nil Coalescing Operator
Optional型の変数の中身がnilの場合にデフォルト値を与えたい場合に有効です。

`COALESCE`といえばSQLの関数にもありますね。"NULL以外の最初の引数を返す"というものです。
Swiftの`Nil Coalescing Operator`という演算子も同様の考え方が使えます。

```swift
optional ?? defaultValue // optionalがnilでない場合はoptinalを、nilの場合はdefaultValueを返す
```

```swift
let myOptioal: String? // Optional<String>で宣言
myOptional = "Angela" // 文字列を代入

let text: String = myOptional ?? "I am the default value"
print(text) // "Angela"が出力される
```

```swift
let myOptioal: String? // Optional<String>で宣言
myOptional = nil // nilを代入

let text: String = myOptional ?? "I am the default value"
print(text) // "I am the default value"が出力される
```

# 5. Optional Chaining
これまではOptional型のStringなどを見てきましたがstructのインスタンスの場合はどうでしょうか。Optional型のユーザー定義のstructを格納する変数や定数が宣言されている場合にも安全にunwrapしたいです。これにはまた別の方法が用意されています。

```swift
struct MyOptional {
  var property = 123
  func method() {
    print("I am the struct's method.")
  }
}

let myOptional: MyOptional? // Optional<MyOptional>で宣言
myOptional = MyOptional() // MyOptionalのインスタンスを代入

print(myOptional?.property) // 123が出力される
myOptional?.method() // "I am the struct's method."が出力される
```

```swift
struct MyOptional {
  var property = 123
  func method() {
    print("I am the struct's method.")
  }
}

let myOptional: MyOptional? // Optional<MyOptional>で宣言
myOptional = nil // nilを代入

print(myOptional?.property) // myOptionalはnilなのでpropertyにはアクセスしない
myOptional?.method() // myOptionalはnilなのでmethodは実行しない
```

# まとめ
Optional型はSwiftの便利な点であると同時に混乱することが多い箇所だと思うので、これらを状況によって使い分けることが大事ですね。

# 参考
[https://developer.apple.com/documentation/swift/optional]()
[https://www.udemy.com/course/ios-13-app-development-bootcamp/]()