Closure in Swift
露出とは
初めてSWIFTに入ったとき、私の一番つらい選択と露出はいったい何だったのだろうか.
簡単に言えば「関数」
Closerとは、短い独立したコードフラグメント関数を指します.
一般的によく知られているC+、Javaで使われているLambda式やObjective Cで使われているBlockと似ています.
SWIFTで一般関数を区別する場合、
- Global Function
- Nested Function
Swiftでは、関数はFirst Class Citizenです.
したがって,変数や定数に関数を割り当てることもパラメータに渡すこともできる.
関数に第1クラスCitizenとしてのこのような権限がある場合、匿名関数であるClosureにもこのような権限があります.
この二つは同等だからです.
しかし、使い方に違いがあります.
Closerの使い方
まず、その表現を見てみましょう.
{ (parameters) -> ReturnType in
statements
}
// or
{ statements }
匿名関数closureは、上記のようにタグ付けできます.以下にGlobal Scope宣言の例を示します.
{ print("Hello") }
上記の例はGlobal Scopeで宣言されていますが、実際には使用できません.全世界で露光を単独で使用することはできないからです.
定数や変数に割り当てるか、関数のパラメータとして使用できます.
let c2 = { (str: String) -> String in
return "Hello, \(str)"
}
上記のコードは使用でき、inキーワードに基づいてモジュールのヘッダとボディを区分することができる.磁気ヘッドには主にパラメータ,リターンに関する情報が含まれ,本体には実行状態に関する情報が含まれている.
多分コード自体を使うのは簡単...swiftプロジェクトでは、コードを見ると、上のような友好的な露出方式はめったに見られないかもしれません.
ほとんどの場合、Optimizationを使用するサムネイルはSyntax Closureであるため、多くのコードがこの傾向に従っています.
Syntax Optimization
前述したように、ほとんどのモジュール式ではSyntax Optimizationが採用されており、SWIFTを使用してコードを書き続ける必要がある場合は、この方法を学ぶ必要があります.
焼き始めの頃はちょっと難しかったですが、ゆっくりしましょう.
let products = [
"Galaxy S", "Galaxy Pro",
"Galaxy Z", "Galaxy S2",
"Galaxy S3", "Galaxy Z Flip",
"Galaxy A51","Galaxy S21",
"Galaxy S20", "Galaxy Note"
]
これらの配列があり、指定されたターゲットは「Pro」を含む要素を検索することです.配列はBuiltin関数として与えられる.filterで簡単に見つけられます.
では.filter要素に何が含まれているか見てみましょう.
以上のように、Parameterは閉鎖的に受信されます.
(String)->次のように、Boolによって受信され、そのまま適用されてコードが記述されます.
products.filter({ (name: String) -> Bool in
return name.contains("Pro")
})
かなり正直なコードを生成できます.しかし、Syntax Optimizationのために、上のコードから1つずつ削除します.
でもここで質問できるのは….
「このように削除すると、コンパイラはどのように認識されますか?」こんな考えがあります.
通常、CompilerはCloserに関する情報を処理し、フレームワーク内で対応するコードからCloserタイプを推定します.
したがって、モジュールからパラメータ、リターンタイプ、inキーワードを削除することで、コンパイルエラーが発生しません.
だから私は1つずつ取り出して、まず閉じたヘッド部分のパラメータタイプと戻り型を取り除くことができます.
products.filter({ (name) in
return name.contains("Pro")
})
その後、inキーを順次クリアしたり、ヘッダのパラメータの代わりにShot Hand Arcgumentを使用してパラメータ名を変更したりすることができます.products.filter({
return $0.contains("Pro")
})
また、単一の戻り文のみが存在する場合はreturnキーワードを省略することもできます.products.filter({
$0.contains("Pro")
})
最後に、Trailing Closeに設定できます.メソッドパラメータがモジュールに含まれていない場合は、カッコを削除することもできます.products.filter() {
$0.contains("Pro")
}
and
products.filter{
$0.contains("Pro")
}
products.filter({ (name: String) -> Bool inreturn name.contains("Pro")
})
これで初期のやつとは違うコードを書くことができます.
比較してみよう
products.filter{ products.filter({ (name: String) -> Bool in
$0.contains("Pro") return name.contains("Pro")
} }
Syntax Optimizationの後,コードは非常に簡単になったことがわかる.Escaping Closure
最後に見たいのはEscaping Closureです.
非常に重要な要素です.
アプリケーション開発とWeb開発は、通信によってアプリケーションを実行するプロセスです.
この場合必要なのは非同期動作であり、SWIFTでこれらの非同期動作を実行する際に使用できるモジュールである.
これがEscaping Closeです.
まずは馬を見ると脱出のCloser
どこから逃げるんだ?!
関数パラメータとしてNon Escaping Closureを使用する場合は、関数の実行順序に依存します.
まず例を挙げます.
func performNonEscaping (closure : () -> ()) {
print("start")
closure()
print("end")
}
performNonEscaping {
print("Closure")
}
以上の結果はstartを無条件に出力し、close->endの順に出力します.すなわち、大外皮関数の実行順序に従って実行することができる.
Escaping Closureは、関数フローに追従しない関数を生成します.
Escappingを行うと元の関数に依存しないため、関数が終了してもClosureを終了する必要はありません.
すなわち,パラメータとしての関数の流れから逸脱する.
この方式の利点は、「閉鎖」の開始および終了が特定できないため、非同期動作が可能であることである.
func performEscaping(closure: @escaping () -> ()) {
print("start")
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
closure()
}
print("end")
}
前述したように,パラメータ閉包に@experitキーワード記述コードを加えることで,Escaping Closeを容易に生成できる.コードの実行結果は次のとおりです.
start
end
Closure
start->endとendが現れると、円関数PerformEscapping関数は終了しますが、内部で実行されているclosureは、完全にハングアップするのではなく、3秒後に実行を決定します.この状態のEscaping Closureを、関数の実行結果に関係なく通信する必要があるコードに使用すると、非常に役に立つと思います.
Reference
この問題について(Closure in Swift), 我々は、より多くの情報をここで見つけました https://velog.io/@hzw94/Closure-in-Swiftテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol