オプショナルが nil
でない場合にプロパティやメソッド、サブスクリプトを呼び出したいオプショナル値の後にクエスチョンマーク (?
) を置いて、オプショナルチェーンを指定します。オプショナル値のアンラップを強制するためにオプショナル値の後にエクスクラメーションマーク (!
) を置くことによく似ています。一番の違いは、オプショナルチェーンはオプショナルが nil
のときうまく失敗しますが、強制アンラップはオプショナルが nil
のとき実行時エラーを起こすことです。
オプショナルチェーンを nil
の値に対して呼び出せることを反映して、問い合わせたプロパティやメソッド、サブスクリプトがオプショナルでない値を返す場合でも、オプショナルチェーン呼び出しの結果は常にオプショナル値となります。オプショナルチェーン呼び出しが成功した(返されたオプショナルに値がある)か、チェーンに nil
値があったために成功しなかった(返されたオプショナル値が nil
)かを確認するために、この返されたオプショナル値を使用することができます。
具体的には、オプショナルチェーン呼び出しの結果は、期待される戻り値と同じ型になりますが、オプショナルにラップされています。通常 Int
を返すプロパティは、オプショナルチェーンでアクセスされるときには Int?
を返します。
次からのいくつかのコードスニペットでは、オプショナルチェーンがどのように強制アンラップと異なるかや、どのようにして成功を確認するかを示しています。
初めに、2 つのクラス Person
と Residence
が定義されています。
class Person {
var residence: Residence?
}
class Residence {
var numberOfRooms = 1
}
Residence
のインスタンスには、デフォルト値 1
の Int
プロパティ numberOfRooms
があります。Person
のインスタンスには、Residence?
型のオプショナル residence
プロパティがあります。
新しい Person
インスタンスを生成した場合、residence
プロパティはオプショナルであるためデフォルトの nil
に初期化されます。次のコードでは、john
には nil
値の residence
プロパティがあります。
let john = Person()
値のアンラップを強制するために residence
の後にエクスクラメーションマークを置いて、この人の residence
の numberOfRooms
プロパティにアクセスしようとすると、存在しない residence
値をアンラップすることになり、実行時エラーを起こします。
let roomCount = john.residence!.numberOfRooms
// 実行時エラーを起こす
このコードは john.residence
に nil
でない値があるときには成功し、適切な部屋数を含む Int
値を roomCount
に設定にします。ですが、上述したように、このコードは residence
が nil
のときには常に実行時エラーを起こします。
オプショナルチェーンは numberOfRooms
の値にアクセスするためのより効果的で害の少ない方法です。オプショナルチェーンを利用するには、エクスクラメーションマークの代わりにクエスチョンマークを使用します。
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// "Unable to retrieve the number of rooms." と出力
このようにして Swift にオプショナル residence
プロパティを「チェーン」させて、residence
が存在する場合には numberOfRooms
の値を取り出します。
numberOfRooms
にアクセスする試みは失敗する可能性があるため、オプショナルチェーンは Int?
型、つまりオプショナル Int
型の値を返します。上の例で見たように、residence
が nil
のときには、numberOfRooms
にアクセスできないことを反映して、このオプショナル Int
もまた nil
となります。このオプショナル Int
はオプショナルバインディングでアクセスされていて、オプショナルでない値を整数にアンラップして roomCount
変数に代入します。
numberOfRooms
がオプショナルでない Int
の場合にでもそうなることに注目してください。オプショナルチェーンで問い合わせされることにより、numberOfRooms
の呼び出しは常に Int
ではなく Int?
を返します。
john.residence
に Residence
インスタンスを代入することで、nil
値ではなくなります。
john.residence = Residence()
この時点で、john.residence
は nil
ではなく、Residence
インスタンスを含んでいます。前と同じようにしてオプショナルチェーンで numberOfRooms
にアクセスすると、numberOfRooms
のデフォルト値 1
を含む Int?
を返します。
if let roomCount = john.residence?.numberOfRooms {
print("John's residence has \(roomCount) room(s).")
} else {
print("Unable to retrieve the number of rooms.")
}
// "John's residence has 1 room(s)." と出力
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.