値が存在しない場合があるような状況では、オプショナルを使用します。オプショナルとは、以下のどちらかです。

  • 値があり、x と等しい

または

  • 値が無い
NOTE
オプショナルの概念は、C や Objective-C にはありません。Objective-C で近いものとして、メソッドがオブジェクトを返す、または有効なオブジェクトが存在しないことを意味する nil を返すようにできることです。しかしながら、これはオブジェクトでのみ有効で、構造体や、C の型、列挙型の値ではできません。これらの型では、Objective-C のメソッドは値が存在しないことを示すための(NSNotFound のような)特別な値を返すようにします。このアプローチは、メソッドを呼び出す側が特別な値があることを把握していることを前提としています。Swift のオプショナルは、特別な定数を必要とせずに、どんな型に対してでも値が存在しないことを示します。

この例では、値が存在しないことに対処するために、オプショナルがどのように使われるかを示す例です。Swift の Int 型には、String 値を Int 値に変換するイニシャライザがあります。しかし、あらゆる文字列が整数に変換できるわけではありません。文字列 "123" は、数値 123 に変換できますが、文字列 "hello, world" は数値に変換できません。

次の例は、String を Int に変換するイニシャライザを使用しています。

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// convertedNumber は "Int?" 型、あるいは "optional Int" と推論される

イニシャライザが失敗する場合があるため、Int ではなく、オプショナル Int を返します。オプショナル Intは、Int でなく、Int? と記述します。クエスチョンマークは、値がオプショナルであることを示します。つまり、Int 値を含んでいるか、または値が存在しないことを意味します。(Bool 値や String 値にはなりえず、Intまたは存在しないのいずれかです。)

nil

オプショナル変数に特別な値 nil を代入して、値が存在しない状態にします。

var serverResponseCode: Int? = 404
// serverResponseCode は Int 値 404
serverResponseCode = nil
// serverResponseCode には値が存在しない
NOTE
nil をオプショナルでない定数や変数に使うことはできません。定数または変数が、ある条件において値が存在しない状態を扱う必要がある場合は、適切な型のオプショナル値として宣言してください。

デフォルト値を指定せずにオプショナル変数を定義する場合、その変数には自動的に nil が設定されます。

var surveyAnswer: String?
// surveyAnswer は自動的に nil に設定される
NOTE
Swift の nil は、Objective-C での nil と同じではありません。Objective-C では、nil は存在しないオブジェクトのポインタです。Swift では、nil はポインタではなく、ある型の値が存在しないことです。オブジェクトだけでなく、どんな型のオプショナルにでも nil を設定することが可能です。

If 文と強制アンラップ

オプショナルが、nil ではなく、値を保持しているかどうかを調べるために、if 文を使うことができます。「等価」演算子 (==) または「不等価」演算子 (!=) で比較を行います。

オプショナルに値がある場合、nil に対して「不等価」とみなされます。

if convertedNumber != nil {
    print("convertedNumber contains some integer value.")
}
// "convertedNumber contains some integer value." と出力

オプショナルが値を保持していることを確認した後は、オプショナルの名前の末尾にエクスクラメーションマークを付加して値にアクセスできます。このエクスクラメーションマークは、「このオプショナルが間違いなく値を保持していることがわかっているので、その値を使用する」ということを意味します。これをオプショナル値の強制アンラップと呼びます。

if convertedNumber != nil {
    print("convertedNumber has an integer value of \(convertedNumber!).")
}
// "convertedNumber has an integer value of 123." と出力

if 文についての詳細は、Control Flow で確認してください。

NOTE
値が存在しないオプショナル値を ! でアクセスしようとすると、実行時エラーになります。! を使ってオプショナル値を強制アンラップする前に、nil でないことを常に確認してください。

オプショナルバインディング

オプショナルが値を保持しているかを確認するために、オプショナルバインディングを使用し、その値を一時的な定数として利用できるようにします。オプショナルバインディングは、オプショナルが値を保持していることを確認するために、if および while 文で使用することができます。と同時に、そこで抽出した値を定数に代入します。ifおよび while 文についての詳細は、Control Flow で説明されています。

以下のように、if 文にオプショナルバインディングを記述します。

if let constantName = someOptional {
    statements
}

Optionals セクションにある possibleNumber の例を、強制アンラップではなく、オプショナルバインディングを使って書き直すことができます。

if let actualNumber = Int(possibleNumber) {
    print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {
    print("\'\(possibleNumber)\' could not be converted to an integer")
}
// "'123' has an integer value of 123" と出力される

このコードは、「Int(possibleNumber) によって返されるオプショナルの Int に値がある場合は、そのオプショナルが保持している値を新たな定数 actualNumber に設定する」と読むことができます。

変換が成功する場合、定数 actualNumber を if 文の初めの分岐内で利用できるようになります。オプショナルが保持している値ですでに初期化されているので、! を付けて値にアクセスする必要はありません。この例では、actualNumber は単に変換の結果を出力するために利用されています。

1 つの if 文に複数のオプショナルバインディングを含めることができ、ブール条件をチェックするために where 節を使うことができます。オプショナルバインディングの値が 1 つでも nil である場合や、where 節が false となる場合は、オプショナルバインディング全体が成立しなかったとみなされます。

if let firstNumber = Int("4"), secondNumber = Int("42") where firstNumber < secondNumber {
    print("\(firstNumber) < \(secondNumber)")
}
// "4 < 42" と出力される
NOTE
if 文のオプショナルバインディングによる定数は、if 文の本体でのみ利用することができます。対照的に、guard文による定数は、Early Exit で説明しているように、guard 文の後に続くコード行で利用できます。

無条件アンラップ

上で述べているように、オプショナルは、定数や変数に値が存在しない場合があることを示しています。オプショナルは、値が存在するかを if 文でチェックすることができ、値が存在する場合はオプショナルバインディングでオプショナル値にアクセスして条件付きでアンラップすることができます。

値が設定された後など、オプショナルが常に値が持っていることが、プログラムの構成から明らかな場合もあります。こういったケースでは、常に値があることを前提にして、アクセスのたびにオプショナル値をチェックしてアンラップする処理を削除するほうが効果的です。

こういったオプショナルは、無条件にアンラップされるオプショナルとして定義されます。オプショナルにしたい型の直後にクエスチョンマーク (String?) を置くのではなく、エクスクラメーションマーク (String!) を置いて無条件にアンラップされるオプショナルを記述します。

無条件にアンラップされるオプショナルは、オプショナルが初めに定義された直後で、その後も値が存在していることがあきらかなオプショナル値の場合に効果的です。Swift での主要な用途は、クラスの初期化処理で、Unowned References and Implicitly Unwrapped Optional Properties で説明されています。

無条件にアンラップされるオプショナルは、通常のオプショナルですが、アクセスのたびにオプショナル値をアンラップすることなく、オプショナルでない値のように使うことができます。次の例は、ラップされた String の値にアクセスするとき、オプショナル文字列と、無条件にアンラップされるオプショナル文字列との間での動作の違いを示しています。

let possibleString: String? = "An optional string."
let forcedString: String = possibleString! // エクスクラメーションマークが必要

let assumedString: String! = "An implicitly unwrapped optional string."
let implicitString: String = assumedString // エクスクラメーションマークは不要

無条件にアンラップされるオプショナルを、使用時に自動的にアンラップされることが許可されているオプショナルとして考えることができます。使用するたびにオプショナル名にエクスクラメーションマークを付けるのではなく、宣言時にオプショナルの型にエクスクラメーションマークを付けます。

NOTE
無条件にアンラップされるオプショナルが nil のときに、ラップされている値にアクセスしようとすると、実行時エラーになります。これは、値が存在しない通常のオプショナルに、エクスクラメーションマークを付けた場合とまったく同じ結果です。

値の有無をチェックするために、無条件にアンラップされるオプショナルを、通常のオプショナルと同じように扱うことができます。

if assumedString != nil {
    print(assumedString)
}
// "An implicitly unwrapped optional string." と出力

1 文で値をチェックしてアンラップするために、無条件にアンラップされるオプショナルに、オプショナルバインディングを使うこともできます。

if let definiteString = assumedString {
    print(definiteString)
}
// "An implicitly unwrapped optional string." と出力
Note
変数がどこかで nil になりえる場合は、無条件にアンラップされるオプショナルを使用しません。変数が nil かどうかチェックする必要がある場合には、常に通常のオプショナル型を使用します。

Portions of this page are translations based on work created and shared by Apple and used according to terms described in the Creative Commons Attribution 4.0 International License.