[Swift] @escaping


@escaping

  • Escappingエンクロージャは、エンクロージャが関数のパラメータとして渡されたときに、関数の実行が終了した後に実行されるエンクロージャです.
  • これに対し、
  • Non-Escappingモジュールは、関数の実行が終了する前(すなわち、関数内部で実行されるモジュール)である.
  • Non-Escaping Closure

    func runClosure(closure: () -> Void) {
        closure()
    }
  • はこのように発表した.
    1.runCloseにモジュールを送信
    2.転送されたclosure()を実行します.
    3.運転クローズ
  • Escaping Closure

  • は、主にネットワーク上で処理完了処理プログラム
  • を処理するために用いる.
    class ViewModel {
        var completionhandler: (() -> Void)? = nil
        
        func fetchData(completion: @escaping () -> Void) {
            completionhandler = completion
        }
    }
    完了モジュールは
  • fetchData,
  • に送信される.
  • 完了モジュールはCompletionHandlerに
  • 格納.
  • fetchDataは値を返し、
  • を終了する.
  • エンクロージャ完了
  • 未運転
    ただし、@experit付きエンクロージャでは、必ずしもexperitエンクロージャのみがパラメータとして使用できるとは限りません.

    Non- Escaping Closure + @escaping

    func runClosure(closure: @escaping () -> Void) {
       closure()  // ✅ closure는 non-escaping 클로저이지만 @escaping 사용 가능
    }
    ただし、逆に@exportのないcloserパラメータでは、expose closerを渡すことはできません.

    Escaping Closure + Not @escaping

    class ViewModel {
        var completionhandler: (() -> Void)? = nil
        
        func fetchData(completion: () -> Void) { // ❗️@escaping 누락으로 컴파일 에러 발생!
            completionhandler = completion
        }
    }
    これにより,関数宣言子にすべてのcloserパラメータ@expressionを加えるだけでよいと考えられる.しかし、コンパイラのパフォーマンスを最適化するために、このように分けて使用されます.
    参照元
    non-expervateモジュールは、コンパイラがモジュールの実行をいつ終了するかを知っているため、モジュールで使用される特定のオブジェクトに対するretain、releaseなどの処理を省略することで、オブジェクトのライフサイクルを効率的に管理できる場合がある.
    一方、esacpingモジュールは関数の外で動作するため、モジュールで使用されるオブジェクトを追加の参照ループ(reference cycle)管理して、モジュールが関数の外で正常に動作していることを確認する必要があります.これはコンパイラのパフォーマンスと最適化に影響するため、SWIFTは必要に応じてエスケープモジュールのみを使用します.
    ソース:https://jusung.github.io/Escaping-Closure/