[Swift]フライアウトキャビネット(Escaping closure)について


主な内容:脱出モジュールの概念、脱出モジュールの用途
次の関数には、completionHandlerの後ろにある@escapingがあります.
func dataTask(with url: URL, 
completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask
この文章では、@escapingが何を意味するのか、どこに使用するのかを見てみましょう.
1.脱出室は何ですか.
離脱エンクロージャは、@escapingに接続されたエンクロージャであり、エンクロージャが関数から「離脱」することは、その関数を伝達するパラメータエンクロージャを表すが、関数を返した後に実行される.
2.なぜ脱出室を使うのですか.
関数内部のモジュールパラメータは外部で使用できます.
デフォルトでは、SWIFT 3以降、関数パラメータとしてのモジュールは関数でのみ使用できます.これは、デフォルトでは、モジュールを関数外部のリポジトリに保存したり、GCDを使用して他のスレッドでモジュールを実行したりすることはできません.
ただし、エンクロージャタイプの前に@escapingを付けると、それをポップアップエンクロージャに置き換えることができ、ポップアップエンクロージャはこの関数を返した後に実行され、通常のエンクロージャとは異なり、関数の外に保存したり、他のスレッドで実行したりすることができます.
ただし、ポップアップモジュールを使用して関数を作成すると、関数の実行が終了してもメモリに残り、外部での使用が容易になります.✌️✌️✌️✌️
ポップアップモジュールが使用できない場合は、関数のモジュールパラメータを関数の外にインポートして加工することはできません.したがって、この値を加工しようとするたびに、コードの長さと複雑さを増大させる新しい関数を作成し、加工する必要があります.
+)外付けエンクロージャは、アーキテクチャ設計のシンプル化に役立ちます.
関数間の実行順序を考慮できます.
ポップアップキャビネットは、関数を返して実行するキャビネットであるため、関数間の実行順序を考慮する際に、ポップアップキャビネットを使用してコードを記述できます.複数の非同期タスクを処理する場合、関数の動作順序を指定できます.
3.イジェクトキャビネットの使用
3.1. 関数外で定義された変数に保存
関数内のエンクロージャパラメータを保存するには、関数外で宣言された変数に保存するだけです.次の例では、completionHandlersという名前の変数にsomeFunctionWithEscapingClosureという関数のcloserパラメータcompletionHandlerを追加して格納します.
var completionHandlers = [() -> Void]()

func someFunctionWithEscapingClosure(completionHandler: @escaping() -> Void) {
	completionHandlers.append(completionHandler)
}
3.2.非同期運転
GCDを使用してdispatch queueからキャビネットを非同期で実行すると、キューは後で使用するためにキャビネットをメモリに保存します.この場合、モジュールがいつ実行されるか分かりません.次の例示的な処理は、jsonのurlを含み、DispatchQueue.global(qos: .background).asyncで処理される.
func getJson(path: String, params: [String: Any], completed: @escaping (Result<String, Error>) -> Void) {
    DispatchQueue.global(qos: .background).async {
        do {
            let url = URL(string: path)
            let json = try String(contentsOf: url!, encoding: .utf8)
            DispatchQueue.main.async {
                completed(Result.success(json))
            }
            
        } catch {
            DispatchQueue.main.async {
                completed(Result.failure(error))
            }
        }
    }
}
脱出室を理解してほしい...ここまであわただしく.
References
  • https://docs.swift.org/swift-book/LanguageGuide/Closures.html
  • https://hcn1519.github.io/articles/2017-09/swift_escaping_closure