Swift 6.0 beta 日本語化計画 : Swift 6.0 beta
式
Swift では、式には4種類があります:接頭辞式、挿入辞式、一次式、そして接尾辞式です。式を評価すると値が返るか、副作用を起こすか、またはその両方です。
接頭辞と挿入辞式を使用すると、演算子は、より小さな式になります。一次式は、概念的には、式の最も簡単な種類であり、それらは値にアクセスする方法を提供します。接尾辞式は、接頭辞と挿入辞式のように、関数呼び出しとメンバへのアクセスのような、接尾辞を使用して、より複雑な式をビルドできます。それぞれの種類の式は、以下のセクションで詳細に記載します。
接頭辞式 は式に、オプションの接頭辞演算子を組み合わせたものです。接頭辞演算子は、一つの引数を取り、それらに式が続きます。
これらの演算子の動作については、基本演算子 および 高度な演算子 を参照してください。
Swift 標準ライブラリで提供される演算子については、演算子の宣言 を参照してください。
in-out 式 は、関数呼び出し式に in-out (入出力) 引数として渡される変数をマークします。
in-out パラメータの詳細と例については、In-Out パラメータ を参照してください。
in-out 式は、ポインター型への暗黙的な変換 で説明したように、ポインターが必要なコンテキストで非ポインター引数を提供する場合にも使用されます。
try 式 はエラーを throw できる式が続く try 演算子で構成されています。これは以下の形式を持っています。
try <#expression#>
try 式の値は式の値です。
optional の try 式は、エラーを throw できる式が続く try? 演算子で構成されています。これは以下の形式を持っています。
try? <#expression#>
式 がエラーを throw しない場合は、optional の try 式の値は、式 の値を含む optional です。それ以外の場合は、optional の try 式の値は nil です。
強制 try 式 は、エラーを throw できる式が続く try! 演算子で構成されています。これは以下の形式を持っています:
try! <#expression#>
強制 try 式の値は、式の値です。式 がエラーを throw した場合は、実行時エラーが生成されます。
挿入辞演算子の左辺の式が try、try?、または try! でマークされている場合、その演算子は挿入辞式全体に適用されます。ただし、括弧を使用すると、演算子の適用範囲を明示的に示すことができます。
挿入辞演算子が代入演算子でないか、try 式が括弧で囲まれていない場合は、try 式は、挿入辞演算子の右側に表示できません。
式に try 演算子と await 演算子の両方が含まれる場合は、try 演算子を最初に指定しなければなりません。
詳細および try, try? 及び try! を使用する方法の例については、エラー処理 を参照してください。
await 式は、await 演算子の後に続く非同期操作の結果を使用する式で構成されます。以下のような形式になります。
await <#expression#>
await 式の値は式の値です。
await でマークされた式は、潜在的な一時停止ポイント と呼ばれます。非同期関数の実行は、await でマークされた式ごとに一時停止できます。さらに、同時実行コードの実行は他のポイントで一時停止されることは決してありません。これは、潜在的な一時停止ポイント間のコードは、次の潜在的な一時停止ポイントの前に更新を完了する限り、一時的に不変条件を破る必要がある状態を安全に更新できることを意味します。
await 式は、async(priority:operation:) 関数に渡される末尾のクロージャなどの非同期コンテキスト内でのみ使用できます。defer 文の本体や、同期関数型のオートクロージャには使用できません。
挿入辞演算子の左辺の式が await 演算子でマークされている場合、その演算子は挿入辞式全体に適用されます。ただし、括弧を使用すると、演算子の適用範囲を明示的に示すことができます。
await 式は、挿入辞演算子が代入演算子であるか、または await 式がかっこで囲まれていない限り、挿入辞演算子の右側には使用できません。
式に await 演算子と try 演算子の両方が含まれる場合は、try 演算子を最初に指定しなければなりません。
await-operator → await
挿入辞式 は、その左側と右側の引数として取る式と挿入辞の二項演算子を組み合わせます。これは以下の形式です:
<#left-hand argument#> <#operator#> <#right-hand argument#>
これらの演算子の動作については、基本演算子 と 高度な演算子 を参照してください。
Swift 標準ライブラリで提供される演算子についての詳細は、演算子の宣言 を参照してください。
代入演算子 は、与えられた式に新しい値を設定します。これには以下の形式があります:
<#expression#> = <#value#>
式 の値は、値 を評価して得た値に設定されます。式 がタプルの場合は、値 は同じ数の要素を持つタプルでなければなりません。(入れ子になったタプルも許可されます。) 代入は 式 の対応する部分に 値 の各部分から行われます。例えば:
代入演算子は、全く値を返しません。
三項条件演算子 は、条件の値に基づいて、与えられた2つの値の1つに評価されます。これは以下の形式です:
<#condition#> ? <#expression used if true#> : <#expression used if false#>
条件 が true と評価された場合は、条件演算子は最初の式を評価し、その値を返します。それ以外の場合は、第二式を評価し、その値を返します。未使用の式は評価されません。
三項条件演算子を使用する例については、三項条件演算子 を参照してください。
型キャスト演算子には4つあり、is 演算子、as 演算子、as? 演算子、そして as! 演算子です。
それらは、以下のような形式です:
<#expression#> is <#type#>
<#expression#> as <#type#>
<#expression#> as? <#type#>
<#expression#> as! <#type#>
is 演算子は、実行時に 式 が、指定した type にキャストできるかどうかチェックします。式 が指定された type にキャストできれば true を返します。それ以外の場合は false を返します。
as 演算子は、アップキャストやブリッジのように、キャストが常に成功するとコンパイル時に知られている時、キャストを実行します。アップキャストは、中間変数を使用せずに、その型のスーパータイプのインスタンスとして式を使用できるようになります。以下のアプローチは同じです。
ブリッジでは、新しいインスタンスを作成する必要なしに、NSString のような、それに対応する Foundation 型の String のように Swift 標準ライブラリ型の式を使用することができます。ブリッジの詳細については、Foundation 型で作業する を参照してください。
as? 演算子は、指定した type に 式 の条件キャストを実行します。as? 演算子は、指定した type の optional を返します。実行時に、キャストが成功した場合、式 の値は、optional で包まれ、返されます。そうでない場合、戻り値は nil です。指定した type へのキャストが失敗することが保証されているか、成功することが保証されている場合は、コンパイル時エラーが発生します。
as! 演算子は、指定した 型 (type) に 式 の強制キャストを実行します。as! 演算子は optional の型 ではなく、指定した 型 の値を返します。キャストが失敗した場合、実行時エラーが発生します。x as! T の動作は、(x as? T)! の動作と同じです。
型キャストの更なる情報と型キャスト演算子を使用する際の例に付いては、型キャスト を参照してください。
一次式 は、式の最も基本的な種類です。それらは、接頭辞式、挿入辞式、及び接尾辞式を作るために他のトークンと組み合わせることができ、それら自体で式として使用できます。
リテラル式 は、通常のリテラル (文字列や数字など) か、配列または辞書リテラル、またはプレイグラウンドリテラルのいずれかで構成されます。
リテラル | 型 | 値 |
---|---|---|
#file | String | それがその中に表示されているファイルへのパス。 |
#fileID | String | それがその中に表示されているファイルとモジュールの名前。 |
#filePath | String | それがその中に表示されているファイルへのパス。 |
#line | Int | その上にそれが表示されている行番号。 |
#column | Int | その中にそれが始まる列番号。 |
#function | String | その中にそれが表示されている宣言の名前。 |
#dsohandle | UnsafeRawPointer | DSO (動的共有オブジェクト) ハンドルが、 表示されている場所で使用中です。 |
配列リテラル は、値の順序付けられた集合です。これは以下の形式です:
[<#value 1#>, <#value 2#>, <#...#>]
配列の最後の式は、オプションのカンマで続けることができます。配列リテラルの値は、[T] 型であり、ここで T はその内部の式の型です。複数の型の式がある場合、T は、それらの最も近い共通のスーパータイプです。空の配列リテラルは、角括弧の空のペアを使用して書かれ、指定した型の空の配列を作成するために使用できます。
辞書リテラル は、キーと値のペアの順不同の集合です。これは以下の形式です:
[<#key 1#>: <#value 1#>, <#key 2#>: <#value 2#> , <#...#>]
辞書の最後の式は、オプションのカンマで続けられます。辞書リテラルの値は [Key: Value] 型ですが、ここで Key は、そのキー式の型であり、Value はその値の式の型です。複数の型の式がある場合は、Key と Value は、それぞれの値の最も近い共通のスーパータイプです。空の辞書リテラルは、空の配列リテラルと区別するために、一対の括弧の内側のコロンとして書かれます。([:])。指定したキーと値の型の空の辞書リテラルを作成して空の辞書リテラルを使用できます。
プレイグラウンドのリテラル は、プログラムエディタ内のカラー、ファイル、またはイメージのインタラクティブな表現を作成するために Xcode で使用されます。Xcode の外部のプレーンテキストでのプレイグラウンドのリテラルは特別なリテラル構文を用いて表現されます。
Xcode でのプレイグラウンドのリテラルの使用方法については、Xcode ヘルプの カラー、ファイル、イメージリテラルの追加 を参照してください。
self 式は、それが発生する型の現在の型またはインスタンスへの明示的な参照です。これには、以下の形式があります。
self
self. <#member name#>
self [<#subscript index#> ]
self (<#initializer arguments#>)
self.init(<#initializer arguments#>)
イニシャライザ、サブスクリプト、またはインスタンス・メソッドでは、self は、それが発生する型の現在のインスタンスを参照します。型メソッドでは、self は、それが発生する現在の型を参照します。
self 式は、スコープ内に同じ名前の別の変数がある場合、関数のパラメータのように、区別する方法を提供し、メンバにアクセスする際にスコープを指定するために使用されます。例えば:
値型の変異メソッドでは、self へその値型の新しいインスタンスを代入することができます。例えば:
スーパークラス式 を使うと、そのスーパークラスを、クラスが操作することができます。それは、以下のいずれかの形式です:
super.<#member name#>
super [<#subscript index#>]
super.init(<#initializer arguments#>)
最初の形式は、スーパークラスのメンバにアクセスするために使用されます。第2の形式は、スーパークラスのサブスクリプトの実装にアクセスするために使用されます。3番目の形式は、スーパークラスのイニシャライザにアクセスするために使用されます。
サブクラスは、それらのスーパークラスでの実装を利用するメンバ、サブスクリプト、およびイニシャライザの実装で、スーパークラス式を使用できます。
条件式 は、条件の値に基づいて、与えられた複数の値のうちの 1 つに評価されます。これは以下のいずれかの形式になります。
条件式は、以下の段落で説明する違いを除き、if 文または switch 文と同じ動作と構文を持ちます。
条件式は以下のコンテキストでのみ表示されます。
条件式の分岐は網羅的であり、条件に関係なく式が常に値を生成することを保証します。つまり、各 if 分岐には対応する else 分岐が必要です。
各分岐には、その分岐の条件が true の場合に条件式の値として使用される単一の式、throw 文、または決して返されない関数の呼び出しのいずれかが含まれます。
各分岐は同じ型の値を生成しなければなりません。各分岐の型チェックは独立しているため、分岐に異なる種類のリテラルが含まれている場合や、分岐の値が nil の場合など、値の型を明示的に指定する必要があります。この情報を提供する必要がある場合は、結果が代入される変数に型注釈を追加するか、分岐の値に as キャストを追加します。
result builder (結果ビルダー) 内では、条件式は変数または定数の初期値としてのみ使用できます。この動作は、結果ビルダー内で変数または定数の宣言の外側で if または switch を記述すると、そのコードは分岐文として認識され、結果ビルダーのメソッドの 1 つがそのコードを変換することを意味します。
条件式の分岐の 1 つがスローしている場合でも、条件式を try 式内に配置しないでください。
クロージャ式 は、ラムダ または他のプログラミング言語で 無名関数 としても知られているクロージャを作成します。関数宣言と同様に、クロージャは文を含み、それが囲むスコープから定数と変数をキャプチャします。これは以下の形式です:
{ (<#parameters#> ) -> <#return type#> in
}
パラメータ は、関数の宣言 で説明したように、関数の宣言におけるパラメータと同じ形式を持っています。
クロージャ式に throws または async を記述すると、クロージャがスローするかまたは非同期として明示的にマークできます。
{ (<#parameters#>) async throws -> <#return type#> in
}
クロージャの本体に、網羅的なエラー処理を伴う do 文内に、ネストされていない throws 文または try 式が含まれている場合、クロージャはスローしていると認識されます。スローしているクロージャが単一のタイプのエラーのみをスローする場合、クロージャはそのエラーの型をスローしていると認識されます。それ以外の場合は、任意の Error をスローしていると認識されます。同様に、本体に await 式が含まれている場合、それは非同期であると認識されます。
クロージャを、より簡潔に書くことができるいくつかの特別な形式があります。
以下のクロージャ式は等価です。
関数の引数としてクロージャを渡す方法については、関数呼び出し式 を参照してください。
クロージャ式は、関数呼び出しの一環としてクロージャをすぐに使用する場合など、変数や定数に格納されなくても使用できます。上記のコードで myFunction に渡されるクロージャ式は、この種のすぐに使用する例です。結果として、クロージャ式がエスケープしているかエスケープしていないかは、その式の周囲のコンテキストによって決まります。クロージャ式がすぐ呼び出されるか、またはエスケープされていない関数の引数として渡された場合、クロージャ式はエスケープしていません。それ以外の場合は、クロージャ式はエスケープしています。
クロージャをエスケープする方法の詳細については、クロージャのエスケープ を参照してください。
デフォルトでは、クロージャ式は、その周囲のスコープからそれらの値への強い参照を使って定数や変数をキャプチャします。キャプチャ・リスト を、値がどのようにクロージャでキャプチャされるか、明示的に制御するのに使用できます。
キャプチャ・リストは、パラメータのリストの前に、角括弧で囲まれカンマ区切りの式のリストとして書かれます。キャプチャ・リストを使用する場合、パラメータ名、パラメータ型、戻り値の型を省略している場合でも、in キーワードも使用しなければなりません。
キャプチャ・リストのエントリは、クロージャが作成される時、初期化されます。キャプチャ・リスト内の各エントリについて、定数は、周囲のスコープ内で同じ名前を持つ定数または変数の値に初期化されます。以下のコードの例では、a はキャプチャ・リストに含まれますが、b は含まれず、それらに異なる動作を与えます。
2つの異なる名前のついたもの a と、周囲のスコープ内の変数と、クロージャのスコープ内の定数で、一つだけの名前の付いた変数の b があります。内側のスコープ内の a はクロージャが作成される時、外側のスコープ内の a の値で初期化されますが、それらの値は、いかなる特別な方法でも接続されてはいません。これは、外側のスコープ内の a の値への変化は、内側のスコープ内の a の値に影響を与えないことを意味し、またクロージャ内部の a への変更がクロージャ外側の a の値に影響を与えない事を意味します。これとは対照的に、一つだけ b という変数があり、外側のスコープでの b であり、クロージャの内側または外側からの変更は、両方の場所から見えます。
キャプチャされた変数の型が参照する意味がある場合は、この区別は見えません。たとえば、以下のコードでは x という名前のついた物が2つあり、外側のスコープ内の変数と内側のスコープ内での定数ですが、それらの両方とも、参照の意味で同じオブジェクトを参照しています。
式の値の型がクラスである場合、弱いまたは所有されない参照で式の値をキャプチャするには、キャプチャ・リストの式を weak または unowned でマークできます。
また、キャプチャリストの名前の付いた値に任意の式を結合する事もできます。式は、クロージャが作成された時評価され、値は指定された強度でキャプチャされます。例えば:
クロージャ式の詳細と例については、クロージャ式 を参照してください。キャプチャリストの詳細と例については、クロージャの強い循環参照の解決 を参照してください。
暗黙のメンバ式 は、型推論が暗黙の型を決定できる文脈で、列挙型の case や型メソッドのように型のメンバにアクセスするための近道の方法です。これは以下の形式です:
. <#member name#>
例えば:
推論された型が optional の場合、暗黙的なメンバー式で optional でない型のメンバーを使用することもできます。
暗黙的なメンバー式の後には、接尾辞演算子または 接尾辞の式 にリストされている他の接尾辞の構文を続けることができます。これは、連鎖された暗黙的なメンバー式 と呼ばれます。すべての連鎖された接尾辞の式が同じ型を持つのが一般的ですが、唯一の要件は、連鎖された暗黙的なメンバー式全体が、そのコンテキストによって暗示される型に変換可能である必要があることです。具体的には、暗示された型が optional の場合は optional でない型の値を使用でき、暗示された型がクラス型の場合はそのサブクラスのいずれかの値を使用できます。例えば:
上記のコードでは、x の型はそのコンテキストによって暗示される型と正確に一致し、y の型は SomeClass から SomeClass? に変換可能であり、z の型は SomeSubclass から SomeClass に変換可能です。
括弧で囲まれた式 は、括弧で囲まれた式で構成されています。明示的にグループ化した式で演算の優先順位を指定するために、括弧を使用できます。グループ化する括弧は、式の型を変更しません。例えば、(1) の型は、単純に Int です。
タプル式 は括弧で囲まれた式の、コンマ区切りのリストで構成されています。それぞれの式は、コロン (:) で区切られた、その前の optional の識別子を持つことができます。これは以下の形式を持っています。
( <#identifier 1#>: <#expression 1#>, <#identifier 2#>: <#expression 2#>, <#...#> )
タプル式の各識別子は、タプル式のスコープ内で一意でなければなりません。ネストされたタプル式では、同じレベルのネストする識別子は一意でなければなりません。たとえば、ラベル a が同じレベルで 2 回表示されるため、(a: 10、a: 20) は無効です。ただし、(a: 10,b:(a: 1, x: 2)) は有効です。a は 2 回出現しますが、外側のタプルに 1 回、内側のタプルに 1 回出現するからです。
タプル式はゼロ個の式を含むことができ、または2つ以上の式を含むことができます。カッコ内の単一の式は括弧で囲まれた式です。
ワイルドカード式 は、代入の間、値を明示的に無視するために使用されます。たとえば、以下の代入式で 10 は x に代入され、20 は無視されます。
マクロ展開式 は、マクロ名と、それに続く括弧で囲まれたマクロの引数のカンマ区切りリストで構成されます。マクロはコンパイル時に展開されます。マクロ展開式の形式は以下のとおりです。
マクロが引数を取らない場合、マクロ展開式ではマクロ名の後の括弧は省略します。
マクロ展開式は、Swift 標準ライブラリの file( ) および line( ) マクロを除き、パラメータのデフォルト値として使用することはできません。関数またはメソッド パラメータのデフォルト値として使用される場合、これらのマクロは、関数定義に出現する場所ではなく、呼び出しサイトのソースコードの場所を使用して評価されます。
マクロ式を使用して、独立型マクロを呼び出します。添付マクロを呼び出すには、属性 で説明されているカスタム属性構文を使用します。独立型マクロと付属マクロはどちらも以下のように展開されます。
各マクロの展開は独立しており、自己完結的です。ただし、パフォーマンスの最適化のため、Swift はマクロを実装する外部プロセスを開始し、同じプロセスを再利用して複数のマクロを展開する場合があります。マクロを実装する場合、そのコードは、コードが以前に展開したマクロや、現在の時刻などの他の外部状態に依存してはなりません。
ネストされたマクロと複数の役割を持つ付属マクロの場合、展開プロセスが繰り返されます。ネストされたマクロ展開式は、外側から内側に展開されます。たとえば、以下のコードでは、outerMacro(_:) が最初に展開され、innerMacro(_:) への展開されていない呼び出しが、outerMacro(_:) がその入力として受け取る抽象構文ツリーに表示されます。
複数の役割を持つ付属マクロは、役割ごとに 1 回展開されます。各展開は、同じ元の AST をその入力として受け取ります。Swift は、生成されたすべての AST ノードを収集し、それらを AST 内の対応する場所に配置することで、全体的な展開を形成します。
Swift のマクロの概要については、マクロ を参照してください。
キーパス式 は、ある型のプロパティまたはサブスクリプトを参照します。キー値監視などの動的プログラミングタスクでは、キーパス式を使用して下さい。それらは以下の形式です:
\<#type name#>.<#path#>
型名 (type name) は、String,[Int], または Set<Int> などの汎用パラメータを含む具体的な型の名前です。
パス (path) は、プロパティ名、サブスクリプト、optional の連鎖式、および強制開封式で構成されます。これらのキーパス成分のそれぞれは、任意の順序で、必要に応じて何度も繰り返すことができます。
コンパイル時に、キーパス式は KeyPath クラスのインスタンスに置き換えられます。
キーパスを使用して値にアクセスするには、すべての型で使用可能な subscript(keyPath:) サブスクリプトにキーパスを渡します。例えば:
型名(type name) は、型推論が暗黙の型を決定できるコンテキストでは省略できます。以下のコードでは、 \.SomeClass.someProperty の代わりに\.someProperty を使用しています。
パス(path) は self を参照して ID キーパス ( \.self) を作成できます。ID キーパスはインスタンス全体を参照するため、これを使用して単一の手順で変数に格納されているすべてのデータにアクセスして変更できます。例えば:
パス (path) には、プロパティ値のプロパティを参照する複数のプロパティ名をピリオドで区切って含めることができます。以下のコードでは、キーパス式 \OuterStructure.outer.someValue を使用して、OuterStructure 型の outer プロパティの someValue プロパティにアクセスしています。
サブスクリプトのパラメータ型が Hashable プロトコルに準拠しているかぎり、パス(path) には括弧を使用したサブスクリプトを含めることができます。以下の例では、キーパスのサブスクリプトを使用して配列の 2 番目の要素にアクセスします。
サブスクリプトで使用される値は、名前付きの値またはリテラルにすることができます。値は、値の意味を使用してキーパスにキャプチャされます。以下のコードでは、key-path 式とクロージャの両方で変数 index を使用して、greetings 配列の 3 番目の要素にアクセスします。index が変更されると、キーパス式はまだ 3 番目の要素を参照しますが、クロージャは新しいインデックスを使用します。
パス(path) には、optional の連鎖と強制開封を使用できます。以下のコードでは、キーパスで optional の連鎖を使用して、optional の文字列のプロパティにアクセスしています。
キーパスの成分を混在させて一致させることで、ある型のなかで深くネストされた値にアクセスできます。以下のコードは、これらの成分を結合するキーパス式を使用して、配列の辞書の異なる値とプロパティにアクセスしています。
通常は関数またはクロージャを提供する文脈で、キーパス式を使用できます。具体的には、関数または型のクロージャ (SomeType) -> Value の代わりに、そのルート型が SomeType であり、そのパス (path) が Value 型の値を生成するキーパス式を使用できます。
キーパス式の副作用は、式が評価される点でのみ評価される事です。たとえば、キーパス式のサブスクリプト内で関数呼び出しを行う場合、関数は、キーパスが使用されるたびにではなく、式の評価の一部として 1 回だけ呼び出されます。
Objective-C の API を操作するコードでキーパスを使用する方法の詳細については、Swift で Objective-C 実行時機能を使用する を参照して下さい。キー値コーディングとキー値監視については、キー値コーディングプログラミングガイド (原文はこちら) および キー値監視プログラミングガイド (原文はこちら) を参照してください。
セレクタ式では、Objective-C でのメソッドまたはプロパティのゲッタやセッタを参照するために使用されるセレクタにアクセスできます。これは、以下の形式です。
#selector(<#method name#>)
#selector(getter : <#property name#>)
#selector(setter : <#property name#>)
メソッド名 (method name) と プロパティ名 (property name) は、Objective-C の実行時に利用できるメソッドまたはプロパティへの参照でなければなりません。セレクタ式の値は、Selector 型のインスタンスです。例えば:
プロパティのゲッタ用のセレクタを作成する場合、プロパティ名 は、変数または定数プロパティへの参照になることができます。それに対し、プロパティのセッタ用のセレクタを作成するときには、プロパティ名 は、変数プロパティのみへの参照でなければなりません。
メソッド名 は、as 演算子と同様に、グループ化するのに括弧を含める事ができ、名前を共有するが異なる型のシグナチャを持つメソッドの間で明確にすることができます。例えば:
セレクタは、実行時にではなく、コンパイル時に作成されるため、コンパイラは、メソッドやプロパティが存在し、それらは Objective-C 実行時に expose されている事を確認できます。
Objective-C の API を操作する Swift コードでのセレクタを使用する方法の詳細については、Swift で Objective-C 実行時機能を使用する を参照してください。
キーパス文字列式を使用すると、Objective-C でのプロパティを参照するために使用される文字列にアクセスし、キー値コーディングおよびキー値監視 API で使用できます。これは以下の形式を持ちます:
#keyPath( <#property name#>)
プロパティ名 (property name) は、Objective-C 実行時環境で使用可能なプロパティへの参照でなければなりません。コンパイル時に、キーパス文字列式は文字列リテラルに置き換えられます。例えば:
クラス内でキーパス文字列式を使用する場合は、クラス名なしで、プロパティ名だけを記述することで、そのクラスのプロパティを参照できます。
キーパス文字列は実行時ではなくコンパイル時に作成されるため、コンパイラはプロパティが存在し、プロパティが Objective-C 実行時環境に expose されていることを確認できます。
Objective-C API を操作する Swift コードでキーパスを使用する方法の詳細については、Swift で Objective-C 実行時機能を使用する を参照して下さい。キー値コーディングとキー値監視については、キー値コーディングプログラミングガイド (原文はこちら) および キー値監視プログラミングガイド (原文はこちら) を参照してください。
接尾辞の式 は、接尾辞演算子または他の接尾辞構文を式に当てはめて形成されます。構文的には、すべての一次式は、また接尾辞式です。
これらの演算子の動作については、基本演算子 および 高度な演算子 を参照してください。
Swift の標準ライブラリで提供される演算子の詳細については、演算子の宣言 を参照してください。
関数呼び出し式 は、関数名と、カッコ内の関数の引数をカンマで区切ったリストが続いて構成されています。関数呼び出し式は、以下のような形式です。
<#function name#>(<#argument value 1#>, <#argument value 2#>)
関数名 は、式の値が関数の型である、任意の式でありえます。
関数の定義が、そのパラメータの名前を含んでいる場合は、関数呼び出しには、コロン (:) で区切られた引数値の前に、名前を含んでいなければなりません。この種の関数呼び出し式の形式は以下のとおりです。
<#function name#>(<#argument name 1#>: <#argument value 1#>, <#argument name 2:
<#argument value 2#>)
関数呼び出し式は、閉じ括弧の直後にクロージャ式の形式が末尾に続くクロージャを含めることができます。末尾に続くクロージャは、最後の括弧内の引数の後に追加された、関数への引数として理解されます。最初のクロージャ式にはラベルが付いていません。追加のクロージャ式の前には、その引数ラベルが付いています。以下の例は、末尾のクロージャ構文を使用する関数呼び出しと使用しないものの同等のバージョンを示しています。
末尾に続くクロージャが、関数の唯一の引数である場合は、括弧を省略することができます。
引数に、末尾に続くクロージャを含めるためには、コンパイラは関数のパラメータを左から右に調べます。以下のように:
末尾に続く クロージャ | パラメータ | アクション |
ラベル付き | ラベル付き | ラベルが同じである場合、クロージャはパラメータと一致します。それ以外の場合、パラメータはスキップされます。 |
ラベル付き | ラベルなし | パラメータはスキップされます。 |
ラベルなし | ラベル付き または ラベルなし | 以下に定義するように、パラメータが構造的に関数型に類似している場合、クロージャはパラメータと一致します。それ以外の場合、パラメータはスキップされます。 |
末尾に続くクロージャは、一致するパラメータの引数として渡されます。スキャンするプロセス中にスキップされたパラメータには、それに渡される引数はありません。たとえば、デフォルトのパラメータを使用できます。一致するものを見つけた後、スキャンは次の末尾に続くクロージャと次のパラメータで続行されます。一致するプロセスの最後に、すべての末尾に続くクロージャが一致しなければなりません。
パラメータが in-out パラメータではなく、パラメータが以下のいずれかである場合、パラメータは関数型に 構造的に似ています。
末尾に続くクロージャが、その型が関数型に構造的に似ているが関数ではないパラメータと一致する場合、クロージャは必要に応じて包み込まれます。たとえば、パラメータの型が optional の型である場合、クロージャは自動的に Optional に包み込まれます。
この一致を右から左に実行していた、5.3 より前のバージョンの Swift からのコードの移行を容易にするために、コンパイラは左から右と右から左の両方の順序をチェックします。スキャン方向によって異なる結果が生成される場合は、古い右から左への順序が使用され、コンパイラは警告を生成します。Swift の将来のバージョンでは、常に左から右の順序が使用されます。
上記の例では、"Ambiguous" とマークされた関数呼び出しは "-120" を出力し、Swift 5.3 上ではコンパイラ警告を生成します。Swift の将来のバージョンでは、"110-" が出力されるでしょう。
クラス、構造体、または列挙型は、特別な名前のメソッド で説明したように、いくつかのメソッドの 1 つを宣言することにより、関数呼び出し構文のシンタックスシュガーを有効にできます。
関数呼び出し式で、引数とパラメータの型が異なる場合、コンパイラは、以下のリストにある暗黙的な変換のいずれか一つを適用して、それらの型を一致させようとします。
以下の 2 つの関数呼び出しは同等です。
これらの暗黙的な変換によって作成されたポインタは、関数呼び出しの間のみ有効です。未定義の動作を回避するには、関数呼び出しの終了後にコードがポインタを決して永続化しないようにしてください。
配列を安全でないポインタに暗黙的に変換する場合、Swift は必要に応じて配列を変換またはコピーすることで、配列の保管記憶場所が連続していることを保証します。たとえば、その保管記憶場所に関して API の契約を作成しない NSArray サブクラスから Array にブリッジされた配列でこの構文を使用できます。配列の保管記憶場所がすでに連続していることを保証する必要があり、暗黙的な変換でこの作業を行う必要がない場合は、Array の代わりに ContiguousArray を使用します。
withUnsafePointer(to:) のような明示的な関数の代わりに & を使用すると、特に関数が複数のポインタ引数を取る場合に、低レベルの C 関数の呼び出しをより読みやすくすることができます。ただし、他の Swift コードから関数を呼び出す場合は、安全でない API を明示的に使用するのではなく、& の使用を避けてください。
イニシャライザ式 は、型のイニシャライザへのアクセスを提供します。これは以下の形式です:
<#expression#>.init(<#initializer arguments#>)
型の新しいインスタンスを初期化する関数呼び出し式でイニシャライザ式を使用して下さい。また、スーパークラスのイニシャライザにデリゲートするイニシャライザ式も使用できます。
関数のように、イニシャライザは値として使用できます。例えば:
名前で型を指定する場合は、イニシャライザ式を使用せずに、型イニシャライザにアクセスできます。他のすべての場合では、イニシャライザ式を使用しなければなりません。
明示的なメンバ式 は、名前付きの型、タプル、またはモジュールのメンバへのアクセスを可能にします。それは、項目とそのメンバの識別子との間のピリオド (.) で構成されています。
<#expression#>.<#member name#>
名前付きの型のメンバは、型の宣言または拡張機能の一部として命名されます。例えば:
タプルのメンバは、表示される順にゼロから始まる整数を使って、暗黙のうちに名前が付けられます。例えば:
モジュールのメンバは、そのモジュールの最上位レベルの宣言にアクセスします。
dynamicMemberLookup 属性で宣言された型には、属性 で説明したように、実行時に検索されるメンバが含まれます。
引数の名前によってのみその名前が異なるメソッドまたはイニシャライザを区別するには、コロン(:) が続く各引数名で、括弧内の引数名を含めて下さい。名前のない引数ではアンダースコア(_) を書きます。オーバーロードされたメソッド間を区別するためには、型注釈を使用して下さい。例えば:
ピリオドが行の先頭に表示されている場合、それは暗黙のメンバ式としてではなく、明示的なメンバ式の一部として理解されます。たとえば、以下のリストは、連鎖したメソッドの呼び出しが複数の行にわたって分割されている事を示します。
この複数行の連鎖構文をコンパイラ制御文と組み合わせて、各メソッドが呼び出されるタイミングを制御できます。たとえば、以下のコードは iOS 上で別のフィルタリングルールを使用します。
#if、#endif、およびその他のコンパイル指示の間に、条件付きコンパイルブロックに暗黙のメンバー式とそれに続く 0 個以上の接尾辞を含めて、接尾辞式を形成できます。別の条件付きコンパイルブロック、またはこれらの式とブロックの組み合わせを含めることもできます。
この構文は、最上位のコードでだけでなく、明示的なメンバー式を記述できる場所ならどこでも使用できます。
条件付きコンパイルブロックでは、#if コンパイル指示の分岐に少なくとも 1 つの式が含まれていなければなりません。他の分岐は空でもかまいません。
接尾辞の self 式は、式または型の名前から成り立ち、直後に .self が続きます。これには、以下の形式があります。
<#expression#>.self
<#type#>.self
最初の形式は 式 の値に評価します。たとえば、x.self は、x と評価します。
二番目の形式は、型 の値に評価します。値としての型にアクセスするにはこの形式を使用して下さい。例えば、SomeClass.self は SomeClass 型自体に評価するため、型レベルの引数を受け取る関数やメソッドにそれを渡すことができます。
サブスクリプト式 は対応するサブスクリプト宣言のゲッタとセッタを使用して、サブスクリプトアクセスを提供します。これは以下の形式です:
<#expression#> [ <#index expressions#> ]
サブスクリプト式の値を評価するために、式 の型のサブスクリプトゲッタは、サブスクリプト・パラメータとして渡された インデックス式 で呼び出されます。その値を設定するためには、サブスクリプト・セッタも同様に呼び出されます。
サブスクリプト宣言の詳細については、プロトコルサブスクリプト宣言 を参照してください。
強制値の式 は、nil でないと確信される、optional の値を開封します。これには以下の形式があります:
<#expression#>!
式 の値が nil でない場合、optional の値は開封され、対応する optional でない型を返します。それ以外の場合は、実行時エラーが発生します。
強制値の式の開封された値は、値自体を変異させることによってか、あるいは値のメンバの一つに代入することによってか、どちらかで変更できます。例えば:
optional の連鎖式 は、接尾辞の式で optional の値を使用するための簡単な構文を提供します。これは以下の形式です:
<#expression#>?
接尾辞の ? 演算子は、式の値を変更せずに式から optional の連鎖式を作ります。
Optional の連鎖式は接尾辞式内に表示されなければならず、接尾辞式は、特別な方法での評価が起こります。optional の連鎖式の値が nil である場合、接尾辞式の他のすべての演算は無視され、全体の接尾辞式は nil に評価されます。optional の連鎖式の値が nil でない場合は、optional の連鎖式の値は開封され、接尾辞式の残りの部分を評価するために使用されます。いずれの場合も、接尾辞式の値はまだ optional の型のままです。
optional の連鎖式を含む接尾辞式が、他の接尾辞式内にネストされている場合、最も外側の式だけが、optional の型を返します。以下の例では、c が nil でない場合、その値は開封されて、 .property を評価するために使用され、その値は .performAction( ) を評価するために使用されます。全体の式 c?.property.performAction( ) は optional の型の値を持っています。
以下の例は、optional の連鎖を使用せずに上記の例の動作を示します。
optional の連鎖式の開封された値は、値自体を変異させることによってか、あるいは値のメンバの一つに代入することによってかのいずれかによって、変更できます。optional の連鎖式の値が nil である場合、代入演算子の右辺の式は評価されません。例えば: