상세 컨텐츠

본문 제목

[Swift] escaping closure

SWIFT

by 옹홍 2021. 8. 2. 02:21

본문

Escaping Closure

Escaping Closure이라고 어디선가 탈출한다는 의미이다. 그렇다면 어디서 탈출하는 것일까?
라는 생각을 해본다면, 함수 라이프사이클이라고 생각하면 난 편했다.

일반적으로 nonescaping 클로저에서는 함수 body에서 호출되고 있는 클로저는 항상 함수가 끝나기 전에 실행된다. 결국 함수 라이프사이클 내에서 실행된다고 볼 수 있다.

nonescaping

func performNonEscaping(closure: () -> ()) {
    print("start")
    closure()
    print("end")
}

performNonEscaping {
    print("closure")
}

이 코드에서 보자면, performNonEscaping()에서는 클로저를 파라미터로 받고있다. 이 클로저는 일반적으로 함수 내에서 만들어진 함수라고 볼 수 있다.(복사본) 그렇게 생각한다면, 함수가 끝나기 전까지 함수 내에 있는 모든 코드는 다 일어날 것이고 다 일어난뒤에는, 메모리가 다 반환되는 것이 정상이다.

하지만 함수 라이프사이클 내에서가 아닌 밖에서 클로저가 사용되어야하는 경우가 있을때, @escaping이라는 annotation을 클로저 앞에 붙인다.
탈출하는것은 함수 라이프사이클 밖에서도 closure가 실행되는 것을 의미한다. 함수의 정상적인 실행흐름을 탈출하는 것이다.
@escaping 클로저는 시작시점과 종료시점이 정확하지 않다. 결국 함수의 실행 흐름과 관련이 없어진다.
보통 비동기프로그래밍을 할때 함수의 실행흐름을 거스를때 사용한다.

escaping

func performEscaping(closure: @escaping () -> ()) {
    print("start")

    var a = 12

    DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
        closure()
        for _ in 0...3 {
            a += 3
        }
        print(a)
    }

    print("end")
}

performEscaping {
    print("closure")
}

이 코드에서 본다면, escaping이 클로저 앞에 붙어있기 때문에 함수가 다 끝난 이후에도 그 클로저는 계속 실행될 예정이라는 것을 알 수 있다.
그러면 함수가 실행되면, 먼저 start가 프린트 되고, 비동기가 있기 때문에, 바로 end가 찍힌다. 이시점에서 performEscaping의 함수의. 라이프사이클은 끝이난다. 하지만 우리는 클로저를 escaping 시켰기 때문에, 이 클로저는 아직 살아있는 것이다.
3초가 지난뒤에 closure()가 발동되서 closure가 찍히고, 그리고 print(a)까지 완성된다.

왜 사용??

클로저의 실행이 완료될때까지 클로저를 제거하지 않는다. 그리고 클로저는 클로저 외부의 값을 캡쳐하고 있기 때문에, 그 값들도 계속 살아있다. 그래서 함수 밖에서 클로저의 기능과 클로저가 캡쳐한 값으로 무언가를 진행할 때 유용하다.

UIKIT에서 어디서 사용되는지는 다음에 정리해보도록 하겠다!

관련글 더보기

댓글 영역