여러 method를 보면 클로저의 타입에 @escaping이란 단어가 붙어 있는게 종종 보입니다.

이게 뭔지 궁금했는데 이제야(?) 알아보려고 합니다!!

그 전에 먼저 @noescape 키워드 부터 알아 보겠습니다.

아래는 공식 문서의 예제 코드입니다.

func someFunctionWithNonescapingClosure(closure: @noescape () -> Void) {
		// 2. do something...

		// 3. 클로저가 실행된다.
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
				// 1. 클로저를 함수의 인자로 전달한다.
        someFunctionWithNonescapingClosure { 
					x = 200 
					// 4. 클로저가 종료되고, 클로저는 메모리에서 지워진다.
				}
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)    // Prints "200"

함수가 실행되면 클로저가 함수의 인자로 전달되고 전달된 클로저는 즉시 실행됩니다.

기본적으로 함수의 인자로 전달된 값은 함수의 외부에서 접근이 불가능합니다. 때문에 함수 안에서만 접근이 가능하죠. 그래서 이름이 탈출불가(?)인가 봅니다...

클로저의 라이프사이클은 위에 표시한 순서대로 실행됩니다.

클로저는 @noescape가 기본값이기 때문에 일반적으로 @noescape 키워드를 사용하지 않습니다!!

이번에는 @escaping 키워드를 예제 코드를 통해 알아 보겠습니다.

var completionHandlers: [() -> Void] = []

func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
    }
}

let instance = SomeClass()
completionHandlers.first?()
print(instance.x)    // Prints "100"

못보던 completionHandlers라는 변수가 생겼습니다!!

이것은 클로저를 저장하는 변수이고, someFunctionWithEscapingClosure 메서드를 보면 클로저를 외부에서 선언한 변수에 저장하는 것을 볼 수 있습니다.

이렇게 @escaping 키워드를 사용하면 함수 외부에서도 클로저에 대해 접근이 가능합니다.

그럼 @escaping 는 어떤 경우에서 사용하는지 보겠습니다.