Swift の Optional

ここでは Swift の Optional についてご説明します。

Swift の Optional とは?

Swift には Optional 型というものがあり、他のデータ型の値が存在するケースと、値が存在しない nil のケースを同じ変数で取り扱えるようになっています。

Optinal という名前の値ありとなしの状態を保持するための enum で、元のデータ型を wrap したような形になっています。


Optional の変数を定義したい時は、データ型の後ろに ? をつけるか、Optional<データ型> のようにデータ型を指定します。

例えば、Optional の Int 型の定数を定義したい時は次のようにできます。

let value1: Int? = 100
let value2: Optional<Int> = 100

print(type(of: value1))
print(type(of: value2))

実行結果は次のようになります。 型を確認すると、Optionall の Int になっていることがわかります。

Optionall<Int>
Optionall<Int>

Swift の Optional の値を unwrap する

Swift の Optional の変数に入っている値を使う時には unwrap をする必要があります。

値が存在していることが確実にわかっている場合は、変数の後ろに ! をつけることで、強制 unwrap することができます。

nil の時はエラーになってしまうのでご注意ください。

let value: Int? = 100

if value != nil {
    print("Value = \(value!)")
} else {
    print("No value exists.")
}

実行結果は次のようになります。

Value = 100

Swift の Optional Binding - if let

Swift の Optional Binding という方法で、Optional の変数に値が存在するかどうかを確認して、存在する時のみその値を定数や変数に代入して続きの処理を行うことができます。

Optional Binding は if 文や while 文などの制御文で使えます。

一番よく使われるのは if let で、先ほどのコードと同じようなことを Optional Binding を使ってやると、次のようになります。

let value: Int? = 100

if let i = value {
    print("Value = \(i)")
    print(type(of: value))
    print(type(of: i))
} else {
    print("No value exists.")
}

実行結果は次のようになります。 value に値が入っている時のみ、i に unwrap された値が入って、if 文のコードブロックが実行されます。

value のデータ型が Optional<Int> なのに対して、i のデータ型が Int になっており、unwrap されているのがわかります。

Value = 100
Optional<Int>
Int

if let で定義した定数 i は if のコードブロック内でしか使えません。

Swift の Optional Binding - guard let

もうひとつ、よく使われる Optional Binding に guard let があります。

guard 文は常に else 文と一緒につかわれ、条件文が true の時だけ guard 文に続く処理をし、そうでない時は return や throw で guard 文のあるスコープを抜けなければなりません。

Optional Binding の guard let を使うことによって、Optional の変数に値が存在する時のみ値を unwrap して続きの処理を行うことができます。

if let では unwrap した定数は if のコードブロック内でしか使えませんでしたが、guard let で定義した定数は、その後でも利用できます。


例えば、関数の中で次のような感じで使えます。

func greet(name: String?) -> String {
    
    guard let name = name else {
        return "No name"
    }
    
    return "Hello, \(name)"
}

print(greet(name: nil))
print(greet(name: "Sakura"))

実行結果は次のようになります。

No name
Hello, Sakura

この場合は guard の後で大したことはしていませんが、続きの処理をするのに値が確実に存在していなければならない、ということをはっきりさせたい時に使うとよいと思います。


Swift の Optional Chaining

Optional の定数や変数があって、wrap したオブジェクトのプロパティやメソッドにエラーを出さずに安全にアクセスしたい時には Optional Chaining が使えます。

Optional Chaining 演算子は ? で、Optional の定数や変数の後ろにつけてから、プロパティやメソッドを呼び出します。

値が nil の時は続くプロパティやメソッドは実行されません。

プロパティやメソッドを使う前に if 文などで、事前に Optional が nil かどうかチェックしなくて良いので便利です。


例えば、Optional の String があって、それに対して Optional Chaining を使って contains() メソッドを呼びたい時は次のようにできます。

let s:String? = "abcde"

if s?.contains("c") == true {
    print("c exists.")
}

実行結果は次のようになります。

c exists.

?? で Optional のデフォルト値を指定する

Optional の値を使う時に ?? 演算子を使って、Optional の値が nil の時のデフォルト値を指定することができます。

例えば、?? 演算子 を使って、Int() のコンストラクタで作った i という Int の Optional 定数が nil の時に "Invalid input" と出力するには、次のようにできます。

let input = "ABC"

let i = Int(input)
print(i ?? "Invalid input")

実行結果は次のようになります。"ABC" が Int に変換できないため i が nil になるので Invalid input と出力されています。 input が整数の文字列の時にはその値が print されます。

Invalid input

以上、Swift の Optional についてご説明しました。

© 2024 iOS 開発入門