kitoko552.memo

kitoko552のメモ

Swiftのオプショナルチェーン(optional chaining)

Swiftのオプショナル型は、値を取り出したいときに開示(unwrap)をしますが、開示した際にnilだった場合、実行時にエラーになってしまいます。

// hoge, fuga, fooのいずれかがnilならエラー
println(hoge!.fuga!.foo!.name)

そのため、nilかどうかをチェックしてから使うと良いです。 ところが、上のようにオプショナル型の変数が多くなるとnilチェックの文が長くなり、相当見にくくなります。

if hoge != nil {
    if fuga != nil {
        if foo != nil {
            println(hoge!.fuga!.foo!.name)
        }
    }
}

オプショナル束縛構文を使っても、ネストは深いままです。

if let h = hoge {
    if let fu = fuga {
        if let fo = foo {
            println(h.fu.fo.name)
        }
    }
}

こういったときに役立つのがオプショナルチェーン(optional chaining)です。 オプショナルチェーンを使うと、上の例が以下のように簡潔になります。

if let name = hoge?.fuga?.foo?.name {
    println(name)
}

オプショナルチェーンでは、?を使ってオプショナル型をつなげます。 こうすると、いずれかのオプショナル型の変数がnilだった場合に、その変数で評価が打ち切られ、nilを返すようになります。 つまり、全て開示できた場合にのみ、最後の値が評価されることになります。

オプショナルチェーンはif文以外でも使うことができます。

var n = hoge?.fuga?.foo?.name

上の場合は、nameがString型だと仮定すれば、変数nはString?型となります。 つまり、全てのオプチョナル型の変数を開示できたらnameがnに入り、開示できなければnilが入ります。

また、オプショナルチェーンは値の参照だけでなく、メソッドの呼び出しにも使えます。

var f = hoge?.fuga?.foo?.hasNext()

hasNextメソッドがBool型だとすると、変数fはBool?型となります。

値を返さないメソッドをオプショナルチェーンで変数に代入した場合、その変数はVoid?型になります。

var v = hoge?.fuga?.foo?.add("hage")

この場合、addが呼び出されていればnilでない値、呼び出されていなければnilになります。 これを利用すると、以下のようにif文に応用することができます。

if hoge?.fuga?.foo?.add("hage") != nil {
    // addが呼び出されていればここにくる
}

オプショナルチェーンは代入先にも使うことができます。

hoge?.fuga?.foo?.name = "alice"

この場合、全てのオプチョナル型の変数を開示できれば、nameに値が代入され、開示できなかった場合は、代入は行われません。

このように、オプショナルチェーンに対する代入は、Void?型を返します。 そのため、以下のように、代入ができたかどうかを調べることができます。

if (hoge?.fuga?.foo?.name = "alice") != nil {
    // 代入が成功したらここにくる
}

※この記事では以下の本を参考にしています。

詳解 Swift

詳解 Swift