あるべるのIT関連メモ

素人エンジニアが何かするときに困ったものなどを参考程度にメモっておこうかと

nilとオプショナル(Optional)型

間が空くといつも忘れるのでいい加減まとめておく。

オプショナル型とは?

Swiftでは通常の変数にnilを代入することは許されていない。nilを代入するためにはオプショナル(Optional)型というもので元のインスタンスをラップする必要がある。イメージは次のような感じか(?)

Optional<T> {
    union {
        T t;
        Nil n;
     }
}

オプショナル型の宣言

オプショナル型の変数は、型の最後に'?'または'!'をつけて宣言する。通常オプショナル型というと'?'で宣言したものを指し、'!'で宣言したものは暗黙的アンラップ オプショナル型になるらしい。両者の違いについては事項で。

var str1: String?
var str2: String!

オプショナル型変数の使用

オプショナル型の変数はアンラップしないと使うことができない。アンラップの仕方は大きく3つあるので1つずつ眺めていく。

強制アンラップ

オプショナル型の変数は使用時に明示的にアンラップ(変数の後ろに!をつける)してやる必要があるのだが、暗黙的アンラップ型で宣言した変数は使用時に自動で=暗黙的にアンラップされる。 ここらへん、C/C++のポインタのように同じ記号の意味が変わるのでイヤらしい。

var str1: String? = "世界"
print("こんにちは" + str1!)     // 変数に!をつけて明示的にアンラップ

var str2: String! = "World"
print("Hello " + str2)        // 特別な操作はせずそのまま使える(自動的にアンラップされる)

nilのチェック付きアンラップ

var hello: String? = "Hello"
print(hello)     // -> Optional("Hello") と表示される

アンラップする際に、値がnilである可能性があるためそれをチェックするための構文が存在する。 以下のコードはhelloがnilだった場合、if文のブロック内のコードは実行されない。

if let hello = hello {
    print(hello)    // -> Hello と表示される
}

オプショナルチェイニング

オプショナル型で宣言したインスタンスのメンバーにアクセスする際にいちいちnilかどうかをチェックするなんてめんどくさいことをしなくてもすむ記法がある。またオプショナルチェイニングでアンラップしたものが返す値はnilでない限りオプショナル型でラップされたものになる。

var obj1: MyClass? = MyClass()
var obj2: MyClass?

obj1?.method()    // obj1 はnilでないのでmethod()が呼ばれる
obj2?.method()    // obj2 はnilなのでmethod()は呼ばれずにnilが返る

obj1?.property    // Optional(property)が返る

感想

オプショナル型を理解してきちんと使えば、nilが紛れ込みにくい堅牢なコードになるはずだが、少し離れると毎回記号の意味を忘れてXcodeのエラーに踊らされてしまう。次からは?や!の意味を忘れても落ち着いてこの記事に帰ってくることでnilのない世界に少しでも近づけるはず。