機能的なスイフト:クロージャ{ }

クレジット:ペクセル

クロージャは、コード内で渡されて使用できる自己完結型の機能ブロックです。

-Apple

クロージャは、定義されているコンテキストから任意の定数や変数への参照をキャプチャして格納することができます。 クロージャは、独自の名前を持たず、その環境から値をキャプチャする関数であると考えることができます。 それらを格納し、関数に引数として渡し、他の値やオブジェクトと同じように扱うことができます。 完了ハンドラとしてクロージャを渡すことは、多くのApiで一般的なパターンです。 標準のSwiftライブラリは、主にイベント処理とコールバックのためにクロージャを使用します。

関数は、特定のタスクを実行する自己完結型のコードのチャンクです。 この名前は、必要に応じてそのタスクを実行するために関数を「呼び出す」ために使用されます。 関数を定義するには、funcキーワードを使用します。 関数は、多くのパラメータ、可変長パラメータにnoneを取り、noneまたは複数のパラメータを返すことができます。

関数は2つのパラメータを取り、1つのパラメータを返します

関数型

関数型は、パラメータ型と関数の戻り値の型で構成されています。 上記の例では、関数の型は次のようになります:(Int, Int) -> Int

これは次のように読むことができます:”タイプInt の両方の2つのパラメータを持ち、タイプIntの値を返す関数。”関数型は、関数のパラメータまたは戻り値の型として設定することができます。

関数型は、次のように任意の変数に割り当てることができます:

var mathFunction: (Int, Int) -> Int = add

関数はクロージャの特殊なケースです。 クロージャは次の三つの形式のいずれかを取ります:

  • グローバル関数:名前があり、値をキャプチャできません。
  • ネストされた関数:名前を持ち、それを囲む関数から値を取得できます。
  • クロージャ式:名前がなく、周囲のコンテキストから値をキャプチャできます。

クロージャ式:

Swift Closure Document

Closureは、中括弧の中に関数型を入れ、戻り値の型の後にinキーワードを入れることで作成できます。

省略形引数名

クロージャ引数は、位置を参照することができます。 , , , というように。

省略名を指定した後は、クロージャ引数を指定する必要はなく、キーワード

でクロージャからの暗黙的な戻り値:

単一式クロージャは、宣言からreturnキーワードを省略することにより、単一式の結果を暗黙的に返すことができます。

複数行式クロージャの場合、returnキーワードは省略できません。

:

関数の最後の引数としてクロージャ式を関数に渡す必要があり、クロージャ式が長すぎる場合は、末尾のクロージャとして書くことができます。 末尾のクロージャは、関数の引数であっても、関数呼び出しのかっこ()の後に書き込まれます。 末尾のクロージャ構文を使用する場合は、関数呼び出しの一部としてクロージャの引数ラベルを記述しません。

メソッド呼び出しの引数としてのクロージャ

末尾のクロージャ( メソッド括弧の後のクロージャ)

closureがメソッドの最後のパラメータである場合、swiftは次のように書くことができます🖕

reduceを使用した末尾のクロージャの例()

末尾のクロージャ構文を使用すると、クロージャ全体をreduce(_:)メソッドの外側の括弧内にラップする必要なく、クロージャがサポートする関数の直後にクロージャの機能をきれいにカプセル化します。

値のキャプチャ:

クロージャは、定義されている周囲のコンテキストから定数と変数をキャプチャできます。 その後、定数と変数を定義した元のスコープが存在しなくなった場合でも、クロージャはそれらの定数と変数の値を本体内から参照して変更できます。

Swiftでは、値をキャプチャできるクロージャの最も単純な形式は、別の関数の本体内に記述されたネストされた関数です。 ネストされた関数は、外部関数の引数のいずれかをキャプチャすることができ、外部関数内で定義された定数と変数をキャプチャすることもで

Swiftドキュメントにある例

このmakeIncrementer関数は、1つの引数、つまりIntを入力として受け入れ、関数型、つまり() -> Intを返します。 これは、単純な値ではなく関数を返すことを意味します。 返される関数にはパラメータがなく、呼び出されるたびにInt値を返します。

ここでamountは引数であり、runningTotalは変数として宣言され、0で初期化されます。 ネストされた関数incrementerは、周囲のコンテキストからamountrunningTotalをキャプチャします。

makeIncrementerを実際に見てみましょう:

メモ: 最適化として、Swiftは代わりに、その値がクロージャによって変更されていない場合、およびクロージャが作成された後に値が変更されていない場合、値のコ

Swiftは、変数が不要になったときに変数を破棄することに関連するすべてのメモリ管理も処理します。

関数の引数で長いクロージャ式を取り除くには、typealiasを使用できます。

非エスケープクロージャ:

クロージャパラメータは、Swift3より前にデフォルトでエスケープされていました。 Swift3では、クロージャパラメータが非エスケープ

としてマークされている場合、クロージャは関数本体をエスケープしません。 関数の引数としてクロージャを渡すと、クロージャは関数の本体で実行され、コンパイラが返されます。 実行が終了すると、渡されたクロージャはスコープ外になり、メモリ内にはもう存在しません。

少なくとも知っておく必要があります

クロージャの実行をエスケープしたい場合は、クロージャのパラメータで@escapingを使用する必要があります。

非エスケープクロージャのライフサイクル:
1。 関数呼び出し中に、関数の引数としてクロージャを渡します。
2. 関数内でいくつかの作業を行い、クロージャを実行します。
3. 関数が返されます。

より良いメモリ管理と最適化のために、Swiftはすべてのクロージャをデフォルトでエスケープしないように変更しました。 CaptureList.swiftはエスケープしないクロージャの例です。

注:@非エスケープ注釈は、関数型

エスケープするクロージャにのみ適用されます:

クロージャは、クロージャが関数に引数として渡されたときに関数をエスケープすると言われますが、関数が戻った後に呼び出されます。 クロージャを@escapingでマークすると、クロージャ内でselfを明示的に参照する必要があります。

1. 関数呼び出し中に、関数の引数としてクロージャを渡します。
2. 関数内でいくつかの追加作業を行います。
3. 関数クロージャを非同期的に実行するか、または格納します。
4. 関数が返されます。

クロージャがデフォルトでエスケープされている場所を見てみましょう:

  • 関数型の変数は暗黙的なエスケープです
  • 型エイリアスは暗黙的なエスケープです
  • オプションのクロージャは暗黙的なエスケープです

一般的なエラー:

非エスケープクロージャをエスケープクロージャに割り当てます。 これを修正するには2つの方法があります:

  • クロージャをエスケープ
  • としてマークするか、クロージャをオプション

Autoclosures:

Swiftの@autoclosure属性を使用すると、自動的にクロージャにラップされる引数を定義できます。 引数を取らず、呼び出されると、その中にラップされている式の値を返します。 この構文上の利便性により、明示的なクロージャの代わりに通常の式を記述することにより、関数のパラメータの周りに中括弧を省略できます。

たとえば、assert(condition:message:file:line:)関数はconditionパラメーターとmessageパラメーターのオートクローズを受け取ります。conditionパラメーターはデバッグビルドでのみ評価され、messageパラメーターはconditionfalseの場合にのみ評価されます。

func assert(_ expression: @autoclosure () -> Bool,
_ message: @autoclosure () -> String) {}

@autoclosure@escaping属性構文で使用するには、次のようにします:

@autoclosure @escaping () -> Bool

クロージャ対ブロック:

“SwiftクロージャとObjective-Cブロックは互換性があるため、ブロックを期待するObjective-CメソッドにSwiftクロージャを渡すことができます。 Swiftのクロージャと関数は同じ型を持っているので、Swift関数の名前を渡すことさえできます。 クロージャはブロックと同様のキャプチャセマンティクスを持っていますが、一つの重要な方法が異なります。 言い換えれば、Objective-Cの__blockの動作は、Swiftの変数のデフォルトの動作です。”

クロージャ対デリゲート:

解決策は問題に依存します。 また、Appleはコールバックパターンに焦点をシフトしています。 UIAlertActionはその一例です。

https://medium.com/@abhimuralidharan/functional-swift-all-about-closures-310bc8af31dd

https://medium.com/@kumarpramod017/what-do-mean-escaping-and-nonescaping-closures-in-swift-d404d721f39d

https://oleb.net/blog/2016/10/optional-non-escaping-closures/

https://swiftunboxed.com/lang/closures-escaping-noescape-swift3/

https://medium.com/@johnsundell/using-autoclosure-when-designing-swift-apis-67fe20a8b2e

コメントを残す

メールアドレスが公開されることはありません。

Previous post 馬の納屋のヒーターの思考-Blackburnの建築家、P.C.:Blackburnの建築家、P.C.
Next post 保証