NSBlogger

意識高いブログ

Swiftの「Optional Value」の使い方

Optional Value

Swiftのコードを読んでいると変数の横に「?」や「!」がついていることがあります。
この「?」がついているものが「Optional Value」になります。

Optional Value の特徴

Optional Valueは「nil」を許容します。
逆にOptional Valueでないものは「nil」を許容しません。

Optional Value の宣言

var optionalValue:String? = "オプショナルです"

型の横に「?」をつけるだけです。
これでnilも代入可能なString型のオブジェクト完成です。

var normalValue:String = "オプショナルじゃない"
normalValue = nil //error

var optionalValue:String? = "オプショナルです"
optionalValue = nil //OK

実際は、Optional<Int>のような型宣言になりますが、「?」をつけるだけでOKです。

nilを許容していないオブジェクトに対してnilを代入しようと、「Could not find an overload for '__conversion' that accepts the supplied arguments」というエラーがでます。

Optional Value を代入するときの注意

Optionalじゃない変数にOptional Valueを代入しようとすると、エラーになります。

let number = "123"
let convertedNumber = number.toInt()

var intNumber:Int = convertedNumber //エラー

Value of optional type 'Int' not unwrapped; did you mean to use '!' or '?' ?」というエラーがでます。
「toInt()」でString型をInt型に変換できます。たとえば上記のような"123"はInt型に正しく変換できますが、"Hello, world"などの文字列はInt型に変換できませんよね。そんな場合はnilとして変換されます。
つまり、toInt()で変換された変数は「nilであるかもしれない」のでOptional Valueとなります。

Optional Valueを代入したいときは、代入先をOptionalにしてあげればOKです。

let number = "123"
let convertedNumber = number.toInt()

var intNumber:Int? = convertedNumber //OK

nilを許容しない変数にOptional Valueを代入したいときはどうすればよいでしょうか。

そこで、オブジェクトが必ずnilじゃない保証があるという前提で、「このオブジェクトはnilではありませんよ」と明示的に宣言するために「!」を使います。

let number = "123"
let convertedNumber = number.toInt()

var intNumber:Int = convertedNumber! //OK  convertedNumberはnilじゃない!

実際はImplicitlyUnwrappedOptional<Int>型になっているようです。

Optionalかどうかを判定する

Optionalかどうかを判定して条件分岐したいときは下記のようにするとよいです。

let number = "123"
let convertedNumber = number.toInt()

if let actualNumber = convertedNumber {
    println("\(actualNumber)はnilじゃないです。")
}else{
    println("nilでした。")
}

まとめ

Objective Cだとnilになっても普通に処理が走ることがありましたが、「?」「!」を使うことでコードを実行する前に「nilをどう扱うか」を制御することができるようになりました。