LoginSignup
1
1

More than 3 years have passed since last update.

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

Posted at

Optional型とは

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

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"とも言うらしい。

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

2. Check for nil value

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

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"が有効。

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は不要となるので便利。

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という演算子も同様の考え方が使えます。

optional ?? defaultValue // optionalがnilでない場合はoptinalを、nilの場合はdefaultValueを返す
let myOptioal: String? // Optional<String>で宣言
myOptional = "Angela" // 文字列を代入

let text: String = myOptional ?? "I am the default value"
print(text) // "Angela"が出力される
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したいです。これにはまた別の方法が用意されています。

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."が出力される
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/

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1