Escaping의 특징을 잘 알지 못하는 분은
https://hj39-develop.tistory.com/143
해당 블로그를 먼저 읽고 와주세요ㅎ
escaping을 사용하기 앞서 클로저는 매개변수로 받아서 사용할 수 있다. (기억하기!)
아래 간단한 예시를 통해 매개변수로 받아온 클로저가 함수를 탈출하는 상황을 봐보자
func test(completion: () -> ()){
print("1")
DispatchQueue.main.asyncAfter(deadline: .now()+2){
print("2")
}
print("3")
}
test { }
print("4")
/*
출력
1
3
4
2
*/
test()는 매개변수로 completion이라는 클로저를 받는다.
test()를 실행할 때 우선 1이 출력된다.
DispatchQueue.main.asyncAfter를 실행하면 2초 뒤에 2가 출력된다.
2초가 지나기 전에 3이 출력되고 그 이후 test()가 종료된다.
종료된 이후에 4가 출력되고 DispatchQueue.main.asyncAfter 잠시 기다렸던 2가 출력되게 된다.
2가 출력될 때 test()는 이미 종료된 상태이다.. (?!)
이런 상황을 탈출했다고 표현한다.
위 예시에서는 DispatchQueue.main.asyncAfter 내부에서 completion을 호출하지 않아서 @escaping 키워드를 사용하지 않아도 오류가 발생하지 않는다.
@escaping을 사용해 보자
func test(completion: @escaping () -> ()){
print("1")
DispatchQueue.main.asyncAfter(deadline: .now()+2){
print("2")
completion()
}
print("3")
}
test {
print("5")
}
print("4")
/*
출력
1
3
4
2
5
*/
첫 번째 예시와 다르게 DispatchQueue.main.asyncAfter 내부에 매개변수로 받아온 클로저 completion를 실행한다.
@escaping 키워드가 없는 경우 compile error가 발생한다.
첫 번째 예시와 같이 1,3,4,2는 같은 방식으로 출력된다.
그 이후 print("5")는 completion으로 전달되는 클로저이므로 completion()이 실행될 때 호출된다.
(느낌이 오겠지만 @escaping 키워드를 사용하여 나중에 실행되는 클로저는 비동기 처리가 된다 ㅎ)
더 신기한 것! 을 찾았다
completion으로 클로저가 올 수도 있고 안 올 수도 있으므로 optional을 붙이면 @escaping을 지우라고 뜨게 된다.
func test(completion: (() -> ())?){
print("1")
DispatchQueue.main.asyncAfter(deadline: .now()+2){
print("2")
completion?()
}
print("3")
}
test {
print("5")
}
print("4")
/*
출력
1
3
4
2
5
*/
optional을 사용하지 않는 경우 completion 타입은 클로저 타입이 되지만 optional 키워드를 붙이는 순간 클로저 타입이 아닌 optional 타입이 된다. 따라서 @escaping 필요 없어지는 것..!
공부할수록 신기한 swift..
# 참고한 사이트
'iOS > Swift 상식' 카테고리의 다른 글
defer (0) | 2023.03.09 |
---|---|
Extension 이란? (0) | 2023.03.08 |
Escaping 개념 (0) | 2023.03.04 |
Mutating (0) | 2023.03.04 |
Hashable 및 Equatable을 상속 받아야 하는 이유 (0) | 2023.03.04 |