escaping 클로저(@escaping)

라무·2023년 8월 9일

정의

💡 Escaping 클로저는 클로저가 함수의 인자로 전달됐을 대, 함수의 실행이 종료된 후 실행되는 클로저이다
  • Non-escaping 클로저는 함수의 실행이 종료되기 전에 실행되는 클로저이다

Non-escaping clousure

실행순서

  1. 클로저가 runClosure()함수의 closure인자로 전달됨
  2. 함수 안에서 closure()가 실행됨
  3. runClosure() 함수가 값을 반환하고 종료됨

→ 클로저가 함수 종료되기 전에 실행되기 때문에 closure()는 Non-escaping 클로저에 해당한다

  • 일반적으로 아무런 키워드 없이 파라미터로 받는 클로저는 모두 non-escaping 클로저에 해당한다
  • 즉, 함수가 종료되고 나서 클로저가 실행할 수 없다
  • 함수가 종료될 때 클로저의 사용도 같이 종료되어야 한다
func runClosure(closure: () -> Void) {
	closure()
}

escaping Closure

실행순서

  1. 클로저가 fetchData()함수의 completion인자로 전달됨
  2. 클로저 completion이 completionhandler변수에 저장된다
  3. fetchData() 함수가 값을 반환하고 종료된다
  4. 클로저 completion은 아직 실행되지 않는다

→ completion은 함수의 실행이 종료되기 전에 실행되지 않는다

  • 함수 밖에서 실행된다
  • 보통 클로저가 다른 변수에 저장되어 나중에 실행되거나 비동기로 실행될 때 escaping 클로저가 사용된다.
  • 함수의 실행 흐름에 상관없이 실행되는 클로저이다
  • 클로저가 함수의 실행의 흐름에 상관없이 실행된다는 것은 → 클로저를 외부로 보낼 수 있다는 것을 의미한다
class ViewModel {
    var completionhandler: (() -> Void)? = nil
    
    func fetchData(completion: @escaping () -> Void) {
        completionhandler = completion
    }
}

예시1

  • completionHandlers.append(completion)를 통해서 withEscaping(completion:) 외부에 클로저를 저장한다
    • 즉, 클로저가 함수를 빠져나갔다

      → 함수를 호출하는 도중에 해당 함수 외부에 클로저를 저장하기 위해서는 클로저는 escaping closure여야 한다

// 함수 외부에 클로저를 저장하는 예시
// 클로저를 저장하는 배열
var completionHandlers: [() -> Void] = []

func withEscaping(completion: @escaping () -> Void) {
    // 함수 밖에 있는 completionHandlers 배열에 해당 클로저를 저장
    completionHandlers.append(completion)
}

func withoutEscaping(completion: () -> Void) {
    completion()
}

class MyClass {
    var x = 10
    func callFunc() {
        withEscaping { self.x = 100 }
        withoutEscaping { x = 200 }
    }
}
let mc = MyClass()
mc.callFunc()
print(mc.x)
completionHandlers.first?()
print(mc.x)

// 결과
// 200
// 100

예시2

참고 사이트

[Swift] Escaping 클로저 (@escaping)

Swift) closure와 @escaping 이해하기

Swift Escaping Closure 이해하기

profile
ios 개발을 하고있는 라무의 사적인 기술 블로그

0개의 댓글