nil
になる可能性のあるオプショナルのプロパティ、メソッド、および subscript を照会して呼び出すためのプロセスです。オプショナルに値が含まれている場合、プロパティ、メソッド、または subscript の呼び出しは成功します。オプショナルが nil
の場合、プロパティ、メソッド、または subscript の呼び出しは nil
を返します。複数を一気にチェーンさせることができ、ある地点で nil
が返ってきた場合、オプショナルチェーン全体が失敗します。NOTE Swift のオプショナルチェーンは、Objective-C のnil
のメッセージングに似ていますが、どの型にでも機能し、成功または失敗をチェックできます。
nil
ではない場合に呼び出したいオプショナルのプロパティ、メソッド、または subscript の後に疑問符(?
)を配置して、オプショナルチェーンを指定します。これは、オプショナルの後に感嘆符(!
)を配置して、その値を強制アンラップするのによく似ています。主な違いは、オプショナルが nil
の場合、オプショナルチェーンが失敗するのに対し、強制アンラップは実行時エラーを引き起こすことです。nil
値で呼び出される可能性があるということを反映するために、照会しているプロパティ、メソッド、または subscript が非オプショナルの値を返した場合でも、オプショナルチェーンの呼び出しの結果は、常にオプショナルになります。このオプショナルの戻り値を使用して、オプショナルチェーンが成功したか(返されたオプショナルに値が含まれているか)、nil
が存在して失敗したか(返されたオプショナルが nil
か)を確認できます。Int
を返すプロパティは Int?
を返します。Person
と Residence
という 2 つのクラスが定義されています:Residence
インスタンスには、numberOfRooms
という Int
プロパティがあり、デフォルト値は 1
です。Person
インスタンスには、Residence?
型の residence
プロパティがあります。Person
インスタンスを作成する場合、その residence
プロパティはオプショナルなため、デフォルトで nil
で初期化されています。下記のコードでは、john
の residence
プロパティは nil
です。residence
の numberOfRooms
プロパティにアクセスしようとすると、residence
の後に感嘆符(!
)を置いてその値を強制アンラップすると、residence
に値がないため、実行時エラーが発生します。john.residence
の値が nil
以外の場合に成功し、roomCount
に適切な部屋数を含む Int
値を設定します。ただし、上に示したように、このコードは、residence
が nil
の場合、常に実行時エラーを引き起こします。numberOfRooms
の値にアクセスする別の方法を提供します。オプショナルチェーンを使用するには、感嘆符(!
)の代わりに疑問符(?
)を使用します:residence
プロパティを「チェーン」し、residence
が存在する場合は numberOfRooms
の値を取得するように Swift に指示します。numberOfRooms
へのアクセスは失敗する可能性があるため、オプショナルチェーンは Int?
型または"オプショナルの Int
"の値を返します。上記の例のように、residence
が nil
の場合、numberOfRooms
にアクセスできなかったことを反映するために、このオプショナルの Int
も nil
になります。オプショナルの Int
は、整数をアンラップし、オプショナルバインディングを介してオプショナルではない値を roomCount
定数に割り当てます。numberOfRooms
がオプショナルではない Int
でも、結果は Int?
になることに注目してください。オプショナルチェーンを介して照会されるため、numberOfRooms
の呼び出しは常に Int
の代わりに Int?
を返します。Residence
インスタンスを john.residence
に割り当てて、nil
値を持たないようにすることができます。john.residence
には、nil
ではなく Residence
インスタンスが含まれるようになりました。以前と同じオプショナルチェーンを使用して numberOfRooms
にアクセスすると、numberOfRooms
のデフォルト値 1
を含んだ Int?
が返されます:Room
および Address
クラスを追加することで、上記の Person
と Residence
モデルを拡張します。Person
クラスは、以前と同じ方法で定義されています:Residence
クラスは以前よりも複雑になっています。今回、Residence
クラスは、[Room]
型の空の配列で初期化される rooms
と呼ばれる変数プロパティを定義します:Residence
は Room
インスタンスの配列を保存するため、その numberOfRooms
プロパティは、格納プロパティではなく、計算プロパティとして実装されています。numberOfRooms
計算プロパティは、単に rooms
配列の count
プロパティの値を返します。rooms
配列にアクセスするためのショートカットとして、このバージョンの Residence
は、rooms
配列内の要求されたインデックスにある部屋へのアクセスを提供する読み書き可能な subscript を提供します。Residence
は、printNumberOfRooms
と呼ばれるメソッドも提供します。このメソッドは、単に住居の部屋数を出力します。Residence
は、Address?
型の address
というオプショナルのプロパティを定義します。このプロパティの Address
クラス型は下記で定義されています。rooms
配列に使用される Room
クラスは、name
という 1 つのプロパティと、そのプロパティを適切な部屋名に設定するイニシャライザを持つシンプルなクラスです:Address
と呼ばれます。このクラスには、String?
型の 3 つのオプショナルプロパティがあります。最初の 2 つのプロパティ buildingName
と buildingNumber
は、特定の建物を住所の一部として識別する別の方法です。3 番目のプロパティ street
は、その住所の通りに名前を付けるために使用されます。Address
クラスはまた、String?
の戻り値の型を持つ buildingIdentifier()
というメソッドも提供します。このメソッドは、住所のプロパティをチェックし、buildingName
に値がある場合は buildingName
を返し、street
と buildingNumber
の両方に値がある場合は 2 つを繋げた値を返し、それ以外は nil
を返しますPerson
インスタンスを作成し、以前と同じように numberOfRooms
プロパティにアクセスしてみます:john.residence
が nil
のため、このオプショナルチェーンは以前と同じように失敗します。john.residence
が現在 nil
のため、john.residence
の address
のプロパティの設定に失敗します。=
演算子の右側のコードはどれも評価されません。前の例では、定数へのアクセスには副作用がないため、someAddress
が評価されないことを確認するのは簡単ではありません。下記のリストは同じ割り当てを行いますが、関数を使用して住所を作成します。この関数は、値を返す前に "Function was called."
と出力します。これにより、=
演算子の右側が評価されたかどうかを確認できます:createAddress()
関数が呼び出されていないことがわかります。Residence
クラスの printNumberOfRooms()
メソッドは、numberOfRooms
の現在の値を出力します。メソッドの外観は次のとおりです:Void
があります。これは、()
の値、または空のタプルを返すことを意味します。Void
ではなく Void?
になります。これにより、メソッド自体が戻り値を定義していなくても、if
文を使用して、printNumberOfRooms()
メソッドを呼び出すことができたかどうかを確認できます。printNumberOfRooms
の呼び出しからの戻り値を nil
と比較して、メソッド呼び出しが成功したかどうかを確認します:residence
プロパティが nil
にもかかわらず、john.residence
のアドレス値を設定しようとしています。オプショナルチェーンによってプロパティを設定しようとすると、Void?
型の値が返されます。これにより、nil
と比較して、プロパティが正常に設定されたかどうかを確認できます:NOTE オプショナルチェーンを通じてオプショナルの subscript にアクセスする場合、疑問符は subscript の大括弧の後(]
)ではなく_前_([
)に置きます。オプショナルチェーンの場合、疑問符(?
)は、常に式のオプショナル部分の直後に続きます。
Residence
クラスで定義された subscript を使用して、john.residence
プロパティの rooms
配列内の最初の部屋の名前を取得しようとしています。john.residence
は現在 nil
のため、subscript の呼び出しは失敗します。john.residence
がオプショナルの値のため、疑問符(?
)は、john.residence
の直後、subscript の括弧([
)の_前に_置かれます。residence
は nil
のため失敗します。john.residence
に Residence
インスタンスを作成して割り当て、その rooms
配列に 1 つ以上の Room
インスタンスを設定すると、Residence
の subscript を使用して、オプショナルチェーンによって rooms
配列内の項目にアクセスできます:Dictionary
型のキーの subscript など) を返す場合、そのオプショナルの戻り値をチェーンさせるために、subscript の閉じ括弧(]
)の_後に_疑問符(?
)を置きます:String
型のキーを Int
型の配列にマップする testScores
という辞書を定義しています。この例では、オプショナルチェーンを使用して、"Dave"
配列の最初の項目を 91
に設定し、"Bev"
配列の最初の項目を 1
ずつ増やし、"Brian"
キーの配列の最初のアイテムを設定しようとします。testScores
辞書には "Dave"
と "Bev"
のキーが含まれているため、最初の 2 つの呼び出しは成功します。しかし、testScores
辞書に "Brian"
のキーが含まれていないため、3 番目の呼び出しは失敗します。Int
の値を取得しようとすると、チェーンの階層数に関係なく、常に Int?
が返されますInt?
の値を取得しようとすると、チェーンの階層数に関係なく、常に Int?
が返されますjohn
の residence
プロパティの address
プロパティの street
プロパティにアクセスしようとしています。ここでは、residence
と address
のプロパティに 2 階層のオプショナルチェーンを使用しています。どちらもオプショナルの型です:john.residence
の値には現在 Residence
インスタンスが含まれています。ただし、john.residence.address
の値は現在 nil
です。このため、john.residence?.address?.street
への呼び出しは失敗します。street
プロパティの値を取得しようとしていることに注目してください。このプロパティの型は String?
です。したがって、2 階層分のオプショナルチェーンが適用されていますが、john.residence?.address?.street
の戻り値も String?
です。john.residence.address
の値として Address
インスタンスを設定し、住所の street
プロパティに値を設定すると、複数階層のオプショナルチェーンを通じて street
プロパティの値にアクセスできます:john.residence
の値に現在 Residence
インスタンスが含まれているため、john.residence
の address
プロパティを設定する試みは成功します。Address
クラスの buildingIdentifier()
メソッドを呼び出します。このメソッドは、String?
型の値を返します。上で説明したように、オプショナルチェーン後のこのメソッド呼び出しの最終的な戻り値の型も String?
です。)
)の_後に_疑問符(?
)を配置します。NOTE 上記の例では、チェーンするオプショナルの値がbuildingIdentifier()
メソッド自体ではなく、buildingIdentifier()
メソッドの戻り値のため、括弧の_後に_疑問符を配置します。