ログアウト

nilとOptional型

何もないことを意味する値nilとOptional型

 nil(ニル)とは、「何もない」ことを表す特別な値です。ただし、空白文字や数値の0とは別物です。変数の初期値としてよく利用されます。

・nilは空白文字や0とは異なる

 「なにもない」ものをコンピュータが扱うことはできません。計算しろ、表示しろ、と言われてもコンピュータは困ります。そのため、Swiftでは普通の定数や変数にnilを入れることはできません。

(つまり、いつも使っている普通の型では、必ず値を入れなければいけません。そのため、宣言後は必ず代入を行わないとエラー表示がでます。)

Swiftでnillを扱うには、Optional(オプショナル)型という特殊な型を使って定数・変数を宣言します。

 

Optional型 

いつも使っている型を、Optional<型> か 型?と記載することで、その定数/変数にnilを入れることができるようになります。(書く手間の少ない「型?」の書き方が一般的です。)

これを「Optional型でラップする」といいます。

ラッピングをすることで、存在する値も、存在しない値も、実体をもたせて扱うことができる、といったイメージです。中身がわからなくなるため、型(データの種類)に「?」をくっつける、と覚えてください。

 

Optional型の扱い方

いざOptional型から値を取り出そう、という時は
①ラップを外してあげる(アンラップ)
②もし中身がnil(なにもない)だったら処理を回避させる の2つが必要になります。

①アンラップ 〜末尾に!をつける〜

上記をPlaygroundで出力結果を試してみてください。ラップされたままだと警告が出ます。

②処理の回避 〜代表的な方法3つ〜

もしラップされた箱から、「何も無い」という値が出てきてそれを出力しろ、計算しろ、と言われるとコンピュータはパニックになり、最悪アプリがエラーで動かなくなります。
安全に動かすためにも、「nilが出てきたら代わりにこれを行ってね、もしくは何もしなくていいよ」という指示を与えます。

1、if構文の条件文で回避

if構文は後ほど詳しく解説いたします。
if に続く str !=  nil   は「strがnilではない場合に、{}内の処理をする、それ以外はこの処理を通らない」という意味の条件文です。

strに中身が入っている場合のみ出力して、というお願いをしています。

2、代入が成功した場合は処理、失敗した場合は回避(if let文)

if に続く let str =  str   は代入を行っており、「この代入が成功したら{}の処理を行う、失敗したらこの処理は通らない」という意味の文章です。if let文と呼ばれます。

あえて同じstrが2回出てきていますが、これはわかりやすく書き直すと以下のようになります。
var str: String? = "コンピュータ"
if let newStr = str {
    print(newStr)
}

つまり、if文の中で新しく宣言した定数(Optional型ではない普通の定数)に、値を移し替えていた、ということです。

if let文で、同じ名前の定数に移し替えた場合には、{ }内の処理ではアンラップ後の定数が優先的に参照されます。そのため同じ変数/定数名を使うことで、新しい変数/定数名を使う手間を省く、という書き方が多くされます。
最初のうちはわかりやすく、別の名前をつけた定数に移し替えても問題ありません。

まとめると、if let文では、代入しようとしたものがnilだったら代入失敗となり、処理が回避されます。
値があった場合は、Optional型でない普通の定数に移し替えて、それを使う、といった方法です。

アンラップ処理後の変数を利用しない場合は、「_(アンダーバー)」で省略することができます。
var str: String? = "コンピュータ"
if let _ = str {
    print("変数はnilではありませんでした")
}

3、nilだった場合は別に用意した値を使って回避

これは、nil対策のために用意された特別な書き方で、
変数がnilでなかったらstrを使用、変数がnilだったら??以降に与えられた値を使用します。

また、定数/変数の宣言時に
let a = b ?? ""
という形で使うこともできます。(bはユーザーが入力した値など、nilの可能性がある値、と考えてみてください)bがnilだったら、""空白文字をaに代入します。もちろん文字列""以外に数字の0なども代わりに扱うことができます。

 

アンラップの手間を省く暗黙的アンラップ型

値を扱う時にアンラップを省略できるOptional型があります。
これを暗黙的アンラップ型(Implicitly Unwrapped Optional)と言います。

Optional型を宣言するときに、?を!にしておくことで、扱う時に自動でアンラップしてくれます。

しかし以前にも説明した通り、何もない値を出力したり計算したりすることはできません。
つまり中身がnilだった場合に出力を命令してしまうと、エラーが発生します。

そのため、値を扱う際に絶対にnilになる可能性がない変数・定数に使います。
それならばOptional型ではない普通の型を使えば良いのでは?とお考えになるでしょう。しかし、実は下記のような場合には必要なのです。

もし、すでにXcodeで「部品をコードと紐づける」という操作を履修した方であればこのようなコードを見たことがあるでしょう。部品をコード化する際、自動で型が暗黙的アンラップ型になっていますね。

なぜnilが入れるようになっているかというと、Xcodeの仕様上、部品を画面に表示するまでの過程でnil(値が確定できない状態の時がある)が入る必要があるからです。

※テキストフィールドやラベルに何も入力されなかった場合は自動的にnilではなく空文字が入るようになっています。普通に使う分には、アンラップなどの手間を考えずに使うことができます。

意識することは少ないでしょうが、型の後ろの!にはこのような意味があることを覚えておいてください。