Swift 4.2 日本語化計画 : Swift 4.2


クロージャ


クロージャ はあなたのコードで渡され使用できる機能の自己完結型のブロックです。Swift におけるクロージャは C と Objective-C のブロックと似ており、他のプログラミング言語でのラムダに似ています。


クロージャは、それらが定義されている文脈から任意の定数および変数への参照をキャプチャし、保存できます。これは、それらの定数や変数の クロージング オーバー として知られています。Swift は、あなたのキャプチャしたメモリ管理のすべてを処理します。


注意: 「キャプチャ」の概念に精通していなくても、心配しないでください。これは、以下の 値のキャプチャ で詳しく説明します。


グローバルと入れ子になった関数は、関数 で紹介したように、実際にはクロージャの特殊なケースです。クロージャは3つの形式のいずれかを取ります:


Swift のクロージャ式は、一般的なシナリオの中に簡単な、すっきりした構文を促す、最適化された、きれいな、明確なスタイルを持っています。これらの最適化は以下のものを含みます:


クロージャ式


入れ子になったた関数は、入れ子になった関数 で紹介したように、より大きな関数の一部として、コードの自己完結型のブロックを命名し、定義する便利な手段です。しかし、それは完全な宣言と名前なしに関数のような形式の短いバージョンを記述するのに便利な場合があります。それらの1つ以上の引数として関数を取る関数やメソッドで作業する場合に特にそれは当てはまります。


クロージャ式 は、簡単に一つの行でクロージャを書く方法で、焦点を当てる構文です。クロージャ式は、明瞭さまたは意向を見失うことなく省略形でクロージャを記述するためのいくつかの構文の最適化を提供します。クロージャ式の例を以下に挙げ、単一の sorted(by:) メソッドの例を繰り返し磨き上げて、これらの最適化を説明し、より簡潔な方法でそれぞれが同じ機能を表現します。


ソートするメソッド


Swift の標準ライブラリは、あなたが提供するソート・クロージャの出力に基づいて、既知の型の値の配列を並べ替える sorted(by:) と呼ばれるメソッドを提供します。それがソート処理を完了すると、sorted(by:) メソッドは正しい順序でその要素を並べ替え、古いものと同じ型とサイズの新しい配列を返します。元の配列は sorted(by:) メソッドによっては変更されません。


クロージャ式の例を以下に挙げ、逆アルファベット順で String 値の配列を並べ替える sorted(by:) メソッドを使用します。ここで並べ替える最初の配列はこうです:


let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]



sorted(by:) メソッドは、配列の内容と同じ型の 2 つの引数を取るクロージャを受け付け、値が一旦並べ替えされると、最初の値が 2 番目の値の前か後かどうかを告げるために Bool 値を返します。並べ替えするクロージャは最初の値が 2 番目の値の になる場合は true を返す必要があり、それ以外の場合は false を返します。


以下の例では、String 値の配列を並べ替え、並べ替えするクロージャは (String, String) -> Bool 型の関数である必要があります。


並べ替えするクロージャを提供する1つの方法は、正しい型の正常な関数を書くことであり、sorted(by:) メソッドに引数としてそれを渡すことです:


  1. func backward(_ s1: String, _ s2: String) -> Bool {
  2.        return s1 > s2
  3. }
  4. var reversedNames = names.sorted(by: backward)
  5. // reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]


最初の文字列(s1)が、第2の文字列(s2)よりも大きい場合、backward(_:_:) 関数は true を返し、s1 が並べ替えされた配列の S2 の前に表示されるべきことを示します。文字列内の文字が、「より大きい」のは 「よりもアルファベットで後に現れる」事を意味します。これは、文字 "B" は文字 "A" 「より大きく」、文字列 "Tom" は文字列 "Tim" よりも大きいことを意味します。これは、逆順のアルファベットの並べ替えを与え、"Barry""Alex" の前に置かれる、などします。


しかし、これは本質的に一つの式の関数 (a > b)が何であるかを書くむしろ長ったらしい方法です。この例では、クロージャ式の構文を使用して、並べ替えるクロージャを一行で記述するほうが好ましいでしょう。



クロージャ式の構文


クロージャ式の構文は、以下の一般的な形式です:


クロージャ式構文の パラメータ は、in-out パラメータである事ができますが、デフォルト値を持つことができません。可変個パラメータに名前を付ければ可変個のパラメータを使用できます。タプルも、パラメータ型及び戻り値型として使用できます。


以下の例では、以前の backward(_:_:) 関数のクロージャ式のバージョンを示しています。


  1. reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
  2.        return s1 > s2
  3. })


この一行に書いたクロージャのパラメータと戻り値の型の宣言が backward(_:_:) 関数の宣言と全く同じであることに注意してください。両方の場合とも、それは (s1: String, s2: String) -> Bool として書かれます。しかし、一行に書いたクロージャ式では、パラメータと戻り値の型はそれらの外ではなく中括弧の に書かれています。


クロージャの本体の先頭は in キーワードによって始まります。このキーワードは、クロージャのパラメータと戻り値の型の定義が終了し、クロージャの本体が、始まろうとしていることを示しています。


クロージャの本体がとても短いので、それは一つの行にさえ書くことができます:


reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )



これは sorted(by:) メソッドへの全体的な呼び出しが同じままであることを示しています。括弧のペアは、まだメソッドの引数全体を包んでいます。しかし、その引数は今一行で書いたクロージャです。


文脈から型を推論


並べ替えるクロージャはメソッドに引数として渡されているので、Swift は、そのパラメータの型と、それが返す値の型を推論できます。sorted(by:) メソッドは、文字列の配列上で呼び出されているので、その引数は (String, String) -> Bool 型の関数でなければなりません。これは (String,String)Bool 型はクロージャ式の定義の一部として書く必要がないことを意味します。型のすべては推測できるので、戻り矢印(->)とパラメータの名前を囲む括弧も省略できます:


reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )



一行のクロージャ式として関数やメソッドにクロージャを渡す時、パラメータの型と戻り値の型を推測することが常に可能です。その結果、クロージャが関数やメソッドの引数として使用される場合、完全な形で一行のクロージャを記述する必要は全くありません。


それにもかかわらず、お望みであれば、型を明示的にもできるし、そしてコードの読者のために曖昧さを回避する場合にはそのように奨励されています。sorted(by:) メソッドの場合、クロージャの目的は、並べ替えが行われている事実から明らかであり、クロージャが文字列の配列の並べ替えを補助しているので、String 値を操作するだろう事を読者は仮定することが安全です。



単一式クロージャからの暗黙的戻り値


単一式のクロージャは、前の例のバージョンのように、それらの宣言から return キーワードを省略して、その単一式の結果を暗黙的に返すことができます。


reversedName = names.sorted(by: { s1, s2 in s1 > s2 } )



ここでは、sorted(by:) メソッドの引数の関数型は、Bool 値がクロージャによって返されなければならないことを明確にしています。クロージャの本体は、Bool 値を返す単一の式(s1 > s2)を含んでいるので、曖昧さはなく、return キーワードを省略できます。



引数名の省略


Swift は、一行で書いたクロージャに引数名の省略を自動的に提供し、$0、$1、$2、 などの名前でクロージャの引数の値を参照するために使用できます。


クロージャ式の中でこれら引数名の省略を使用する時は、その定義からクロージャの引数リストを省略でき、そして省略した引数名の数と型は、予想される関数型から推測されます。クロージャ式は、その本体全体で構成されているため、キーワード in も、省略できます:


reversedNames = names.sorted(by: { $0 > $1 } )



ここで、$0$1 はクロージャの第一及び第二の String 引数を参照しています。



演算子メソッド


上記のクロージャ式を書く、さらに より短い 方法が実際にあります。Swift の String 型は String 型の二つのパラメータを持つメソッドとして大なり演算子(>) の文字列固有の実装を定義し、Bool 型の値を返します。これは正確に sorted(by:) メソッドに必要なメソッド型と一致します。したがって、単に、大なり演算子に渡すことができ、そして Swift は、あなたがその文字列固有の実装を使用したいことを推測します。


reversedNames = names.sorted(by, >)



演算子メソッドの詳細については、演算子メソッド を参照してください。


後続クロージャ


クロージャ式を関数に、関数の最後の引数として渡す時、クロージャ式が長い場合はクロージャ式は、その代わりにそれを 後続クロージャ として書くのが役立ちます。後続クロージャは、それが関数への引数だったとしても、関数呼び出しの括弧の後に書かれます。後続クロージャ構文を使用する時、関数呼び出しの一部としてクロージャの引数ラベルを書いてはいけません。


  1. func someFunctionThatTakesAClosure(closure: () -> Void) {
  2.        // function body goes here
  3. }
  4. // Here's how you call this function without using a trailing closure:
  5. someFunctionThatTakesAClosure(closure: {
  6.        // closure's body goes here
  7. })
  8. // Here's how you call this function with a trailing closure instead:
  9. someFunctionThatTakesAClosure() {
  10.        // trailing closure's body goes here
  11. }


上記の クロージャ式の構文 セクションから文字列並べ替えクロージャを引用すると、後続クロージャーとして sorted(by:) メソッドの括弧の外に書くことができます:


reversedNames = names.sorted() { $0 > $1 }



クロージャ式が関数またはメソッドの唯一の引数として提供される場合、関数を呼び出すときに、後続クロージャとしての式を提供する場合、関数やメソッドの名前の後の括弧 () のペアを記述する必要はありません。


reversedNames = names.sorted { $0 > $1 }


1行にインラインで書くことが不可能であるほどクロージャが十分に長い場合、後続クロージャは最も有用です。例として、Swift の Array 型には、その一つだけの引数としてクロージャ式を取る map(_:) メソッドがあります。クロージャは配列内の各項目に対して一度ずつ呼び出され、その項目に(おそらく他の型の)代替マッピングされた値を返します。マッピングされた性質と戻り値の型はクロージャが指定するのを任されています。


提供されたクロージャを各配列要素に任せた後、map(_:) メソッドは、元の配列内の対応する値と同じ順序で新しくマッピングされたすべての値を含む新しい配列を返します。


ここで、Int 値の配列を String 値の配列に変換するために、後続クロージャと map(_:) メソッドを使用できる方法を示します。配列 [16、58、510] は、新しい配列 ["OneSix","FiveEight","FiveOneZero"] を作成するために使われます:


  1. let digitNames = [
  2.        0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
  3.        5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
  4. ]
  5. let numbers = [16, 58, 510]


上記のコードは、整数の数字とその名前の英語バージョン間のマッピングの辞書を作成します。また、整数の配列も定義し、文字列に変換される準備ができます。


これで、後続クロージャとして配列の map(_:) メソッドにクロージャ式を渡して、String 値の配列を作成するために numbers の配列を使用できます:


  1. let strings = numbers.map { (number) -> String in
  2.        var number = number
  3.        var output = ""
  4.        repeat {
  5.                output = digitNames[number % 10]! + output
  6.                number /= 10
  7.        } while number > 0
  8.        return output
  9. }
  10. // strings is inferred to be of type [String]
  11. // its value is ["OneSix", "FiveEight", "FiveOneZero"]


map(_:) メソッドは、配列内の各項目ごとに一度ずつクロージャ式を呼び出します。マッピングされる配列内の値から型が推測できるので、クロージャの入力パラメータ、number の型を指定する必要はありません。


この例では、値は、クロージャ本体内で変更できるように、変数 number は、クロージャの number パラメータの値で初期化されます。(関数とクロージャへのパラメータは、常に定数です。)クロージャ式はまた、マッピングされた出力配列内に保存される型を示すために、String の戻り値の型も指定します。


クロージャ式は、それが呼び出されるたびに output と呼ばれる文字列をビルドします。これは、剰余演算子 (number % 10) を使用して number の最後の桁を計算し、digitNames 辞書内の適切な文字列を検索するためにこの数字を使います。クロージャは、ゼロより大きい任意の整数の文字列表現を作成するために使われます。


注意: 辞書のサブスクリプトはキーが存在しない場合、辞書の検索が失敗するかもしれないことを示すため optional の値を返すので、digitNames 辞書のサブスクリプトへの呼び出しは、感嘆符 (!) が続いています。上記の例では、number % 10 は、常に digitNames 辞書の有効なサブスクリプトキーである事を保証されており、感嘆符は、サブスクリプトの optional の戻り値に保存されている String 値を強制開封するために使用されます。


digitNames 辞書から得られた文字列は output前に 追加され、効果的に数字の逆順で文字列バージョンをビルドします。(式 number % 10 の値は、16 では 658 では 8510 では 0 を与えます)


number 変数はその後 10 で割られます。それが整数であるため、割り算で切り捨てられ、そのため 161 になり、585 になり、51051 になります。


プロセスは number0 に等しくなるまで続き、その時点で output 文字列がクロージャによって返され、map(_:) メソッドにより出力配列に追加されます。


上記の例では後続クロージャ構文の使用が map(_:) メソッドの外側の括弧内のクロージャ全体を包む必要がなく、クロージャがサポートしているので、関数の直後にクロージャの機能をきちんとカプセル化しています。



値のキャプチャ


クロージャは、それが定義されている周囲の文脈から定数と変数を キャプチャ できます。クロージャは、その定数および変数を定義したオリジナルの範囲がもはや存在しない場合でも、その本体内からそれらの定数と変数の値を参照し、変更できます。


Swift では、値をキャプチャできるクロージャの最も簡単な形式は、別の関数の本体内で書かれた、入れ子になった関数です。入れ子になった関数は、その外側の関数の引数のいずれでもキャプチャでき、また、外側の関数内で定義された全ての定数と変数もキャプチャできます。


ここで入れ子になった incrementer と言う関数を含む makeIncrementer と言う関数の例を挙げましょう。入れ子になった incrementer() 関数は、その周囲の文脈から、二つの値、runningTotalamount をキャプチャします。これらの値をキャプチャした後、incrementeramount によって、それが呼び出されるたびに runningTotal を増分するクロージャとして makeIncrementer によって返されます。


  1. func makeIncrementer(forIncrement amount: Int) -> () -> Int {
  2.        var runningTotal = 0
  3.        func incrementer() -> Int {
  4.                runningTotal += amount
  5.                return runningTotal
  6.        }
  7.        return incrementer
  8. }


makeIncrementer の戻り値の型は () -> Int です。これは、単純な値ではなく、関数 を返すことを意味します。それが返す関数にはパラメータはなく、呼び出されるたびに Int 値を返します。関数が、他の関数を返す方法については、戻り値の型としての関数型 を参照してください。


makeIncrementer(forIncrement:) 関数は、返されるインクリメンタの現在実行中の合計を保存するために、runningTotals と呼ばれる整数の変数を定義しています。この変数は、0 の値で初期化されます。


makeIncrementer(forIncrement:) 関数は forIncrement の引数ラベルと、一つの Int パラメータを持ち、また amount のパラメーター名を持っています。このパラメータに渡された引数の値は、返されたインクリメンタの関数が呼び出されるたびに runningTotal が増分されるべき値を指定します。makeIncrementer 関数は実際の増分を行う、incrementer と言う入れ子になった関数を定義しています。この関数は、単に amountrunningTotal に加算し、その結果を返します。


分離して考えると、入れ子になった incrementer() 関数は珍しく見えるかもしれません:


  1. func incrementer() -> Int {
  2.        runningTotal += amount
  3.        return runningTotal
  4. }


incrementer() 関数は、パラメータを全く持っていないし、まだそれはその関数本体内から runningTotalamount を参照しています。それは、その周囲の関数から runningTotalamount への 参照 をキャプチャする事によってこれを行い、自身の関数本体内でそれらを使用します。参照によりキャプチャする事は runningTotalamount が、makeIncrementer への呼び出しが終了しても消えない事を保証し、また runninTotalincrementer 関数が呼び出される次の回にも使用可能であることも保証します。


注意: 最適化の結果として、Swift はその値がクロージャにより変異されず、及びクロージャが作成された後値が変異されない場合は、代わりに、値の コピー をキャプチャし、保存します。

Swift はまた、それらがもはや必要でない時に変数の処分に関係するすべてのメモリ管理を処理します。


ここで、アクション内の makeIncrementer の例を示します。


let incrementByTen = makeIncrementer(forIncrement: 10)



この例では、その runningTotal 変数に、呼び出されるたびに 10 を追加するインクリメンタ関数を参照する incrementByTen という定数を設定します。関数を複数回呼び出すとこのアクションでの動作がわかるでしょう:


  1. incrementByTen()
  2. // returns a value of 10
  3. incrementByTen()
  4. // returns a value of 20
  5. incrementByTen()
  6. // returns a value of 30


インクリメンタを二回目に作成すると、それは新しい、独立した runningTotal 変数への独自の保存された参照を持つことになるでしょう。


  1. let incrementBySeven = makeIncrementer(forIncrement: 7)
  2. incrementBySeven()
  3. // returns a value of 7


オリジナルのインクリメンタ(incrementByTen)を呼ぶと、再び自身の runningTotal 変数を増分し続け、 incrementBySeven によりキャプチャされた変数には影響しません:


  1. incrementByTen()
  2. // returns a value of 40


注意: もしクラス・インスタンスのプロパティにクロージャを割り当てて、クロージャがインスタンスまたはそのメンバーを参照することで、そのインスタンスをキャプチャする場合は、クロージャとインスタンス間で強い循環参照を作成します。Swift は、これらの強い循環参照を破壊するために キャプチャリスト を使用します。詳細については、クロージャの強い循環参照 を参照してください。


クロージャは参照型


上記の例では、incrementBySevenincrementByTen は定数ですが、これらの定数が参照するクロージャはまだそれらがキャプチャした runningTotal 変数を増分することができます。これは、関数とクロージャが 参照型 のためです。


関数やクロージャを定数または変数に割り当てる時はいつでも、定数または変数が関数またはクロージャへの 参照 であることを実際に設定しています。上記の例では、それは incrementByTen がそれが定数である事に 参照 しているのはクロージャの選択であり、クロージャ自体の内容ではありません。


2つの異なる定数や変数にクロージャを割り当てた場合、それらの定数または変数の両方とも同じクロージャを参照することをこれは意味します。


  1. let alsoIncrementByTen = incrementByTen
  2. alsoIncrementByTen()
  3. // returns a value of 50
  4. incrementByTen()
  5. // returns a value of 60


上記の例は、alsoIncrementByTen の呼び出しが incrementByTen の呼び出しと同じであることを示しています。両方とも同じクロージャを参照するため、両方とも増分して同じ実行中の合計を返します。


クロージャのエスケープ


クロージャは、関数に引数として渡されますが、関数が戻った後に呼び出されるので関数を エスケープ すると言われます。そのパラメータの一つとしてクロージャを取る関数を宣言するときは、クロージャがエスケープするのを許可されていることを示すために、パラメータの型の前に @escaping と書けます。


クロージャがエスケープできる一つの方法は、関数の外で定義された変数に格納されている事です。例として、非同期操作を開始する、多くの関数が完了ハンドラとしてクロージャ引数を取ります。操作を開始した後関数は戻りますが、操作が完了するまでクロージャは呼び出されず、クロージャは後で呼ばれるように、エスケープする必要があります。例えば:


  1. var completionHandlers: [() -> Void] = []
  2. func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
  3.         completionHandlers.append(completionHandler)
  4. }


someFunctionWithEscapingClosure(_:) 関数は、その引数としてクロージャをとり、関数の外で宣言されている配列にそれを追加します。@escaping で、この関数のパラメータをマークしなければ、コンパイル時エラーになるでしょう。


@escaping でクロージャをマークすることは、明示的にクロージャ内の self を参照しなければならないことを意味します。たとえば、以下のコードでは、 someFunctionWithEscapingClosure(_:) に渡されたクロージャはエスケープするクロージャで、明示的に self を参照する必要があることを意味します。これとは対照的に、 someFunctionWithNonescapingClosure(_:) に渡されたクロージャは、エスケープしないクロージャで、それは暗黙のうちに self を参照できることを意味します。


  1. func someFunctionWithNonescapingClosure(closure: () -> Void) {
  2.         closure()
  3. }
  4. class SomeClass {
  5.         var x = 10
  6.         func doSomething() {
  7.                 someFunctionWithEscapingClosure { self.x = 100 }
  8.                 someFunctionWithNonescapingClosure { x = 200 }
  9.         }
  10. }
  11. let instance = SomeClass()
  12. instance.doSomething()
  13. print(instance.x)
  14. // Prints "200"
  15. completionHandlers.first?()
  16. print(instance.x)
  17. // Prints "100"


オートクロージャ


オートクロージャ は関数への引数として渡される式を包み込むために自動的に作成されるクロージャです。これは、引数を全く取りませんし、呼び出された時、その内側に包み込まれていた式の値を返します。この構文上の利便性は、明示的なクロージャの代わりに、正常な式を書くことにより、関数のパラメータの周りのカッコを省略できます。


オートクロージャを取る関数を 呼び出す のが一般的ですが、この種の関数を 実装する のは一般的ではありません。例えば、assert(condition:message:file:line:) 関数は、その conditionmesseage パラメータ用のオートクロージャを取りますが、その condition パラメータはデバッグビルドでのみ評価され、その message パラメータは、conditionfalse の場合にのみ評価されます。


オートクロージャは、あなたがクロージャを呼び出すまで、内部のコードは実行されませんので、評価を遅らせることができます。そのコードが評価されるときには、あなたがコントロールできますので、評価を遅らせることは、副作用を持っているか、計算コストが高い場合に有用です。以下のコードは、クロージャが評価を遅延させる方法を示しています。


  1. var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
  2. print(customersInLine.count)
  3. // Prints "5"
  4. let customerProvider = { customersInLine.remove(at: 0) }
  5. print(customersInLine.count)
  6. // Prints "5"
  7. print("Now serving \(customerProvider())!")
  8. // Prints "Now serving Chris!"
  9. print(customersInLine.count)
  10. // Prints "4"


customersInLine 配列の最初の要素がクロージャ内のコードによって除去されているにもかかわらず、クロージャが実際に呼び出されるまで、配列の要素は除去されません。クロージャが決して呼び出されない場合は、クロージャ内の式は評価されることは決してなく、それは配列の要素が決して除去されないことを意味します。customerProvider の型は String ではなく、文字列を返す、パラメータのない () -> String の関数であることに注意してください。


関数に引数としてクロージャを渡すときは、遅延評価と同じ動作を得られます。


  1. // customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
  2. func serve(customer customerProvider: () -> String) {
  3.         print("Now serving \(customerProvider())!")
  4. }
  5. serve(customer: { customersInLine.remove(at: 0) } )
  6. // Prints "Now serving Alex!"


上記のリストの serve(customer:) 関数は、顧客(customer) の名前を返す、明示的なクロージャをとります。下記の serve(customer:) のバージョンは、同じ操作を実行しますが、明示的なクロージャを取る代わりに、それは @autoclosure 属性でそのパラメータの型をマークすることによってオートクロージャを取ります。それが クロージャではなく、String 引数を取ったかのように、今や、関数を呼び出すことができます。 customerProvider のパラメータの型が @autoclosure 属性でマークされているため、引数は自動的に、クロージャに変換されます。


  1. // customersInLine is ["Ewa", "Barry", "Daniella"]
  2. func serve(customer customerProvider: @autoclosure () -> String) {
  3.         print("Now serving \(customerProvider())!")
  4. }
  5. serve(customer: customersInLine.remove(at: 0))
  6. // Prints "Now serving Ewa!"


注意: オートクロージャの乱用はあなたのコードを理解するのを難しくします。コンテキスト(文脈)と関数名は、評価が延期されていることを明確にする必要があります。

エスケープするのを許可されているオートクロージャが欲しい場合は、@autoclosure@escaping 属性の両方を使用します。@escaping 属性は上記の クロージャのエスケープ で説明しています。


  1. // customersInLine is ["Barry", "Daniella"]
  2. var customerProviders: [() -> String] = []
  3. func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
  4.         customerProviders.append(customerProvider)
  5. }
  6. collectCustomerProviders(customersInLine.remove(at: 0))
  7. collectCustomerProviders(customersInLine.remove(at: 0))
  8. print("Collected \(customerProviders.count) closures.")
  9. // Prints "Collected 2 closures."
  10. for customerProvider in customerProviders {
  11.         print("Now serving \(customerProvider())!")
  12. }
  13. // Prints "Now serving Barry!"
  14. // Prints "Now serving Daniella!"


上記のコードでは、その customerProvider 引数として渡されたクロージャを呼び出す代わりに、collectCustomerProviders(_:) 関数は customerProviders 配列にクロージャを追加します。配列は、関数の範囲外で宣言されており、それは配列の中のクロージャが関数から戻った後に実行できることを意味します。その結果、customerProvider 引数の値は、関数の範囲をエスケープすることを許されていなければなりません。


前:関数 次:列挙型

<BETA SOFTWARE>
このドキュメントには、開発中の API または技術に関する予備的な情報が含まれています。この情報は変更されることがあり、このドキュメントに従って実装されたソフトウェアは、最終的なオペレーティングシステムソフトウェアでテストする必要があります。

Apple の Beta ソフトウエアについての詳細

















トップへ(Swift 4.2)












トップへ(Swift 4.2)












トップへ(Swift 4.2)












トップへ(Swift 4.2)












トップへ(Swift 4.2)












トップへ(Swift 4.2)












トップへ(Swift 4.2)












トップへ(Swift 4.2)












トップへ(Swift 4.2)












トップへ(Swift 4.2)
目次
Xcode 10 の新機能

Swift について
Swift と Cocoa と Objective-C (obsolete)
Swift Blog より (obsolete)

SwiftLogo
  • Swift 4.2 全メニュー


  • Swift へようこそ

  • Swift 言語のガイド
  • 基本演算子
  • 文字列と文字
  • コレクション型
  • フロー制御
  • 関数
  • クロージャ
  • 列挙型
  • クラスと構造体
  • プロパティ
  • メソッド
  • サブスクリプト
  • 継承
  • 初期化
  • デイニシャライザ
  • Optional の連鎖
  • エラー処理
  • 型キャスト
  • ネストした型
  • 拡張機能
  • プロトコル
  • ジェネリック(汎用)
  • 自動参照カウント
  • メモリの安全性
  • アクセス制御
  • 高度な演算子

  • 言語リファレンス

  • マニュアルの変更履歴













  • トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ












    トップへ