@escaping 📑
About @escaping ▾
escaping을 접하다 ▾
func fetchUser(completion: @escaping(User) -> Void) {
...
}
- 위의 코드처럼 통신이나 비동기 처리를 할 때 이러한 코드를 본 적이 있습니다.
- completion 클로저를 파라미터로 작성하면서 @escaping이 붙은 걸 보면서 어떨 때 사용하는지 느낌만 알고, 정확히 어떨 때 사용하며 무엇인지 몰랐습니다.
정의 ▾
- Escaping Closure
- 클로저가 함수의 인자로 전달됐을 때, 함수의 실행이 종료된 후 실행되는 클로저입니다.
- Non-Escaping Closure
- 함수의 실행이 종료되기 전에 실행되는 클로저입니다.
비교하기 ▾
- Non-Escaping Closure
func fetchUser(completion: () -> Void) {
completion()
}
- 실행 순서 ▾
- 클로저가 fetchUser() 함수의 completion 인자로 전달됩니다.
- 함수 안에서 completion() 이 실행됩니다.
- fetchUser() 함수가 값을 반환하며 종료가 됩니다.
- Escaping Closure
class UserViewModel {
var completionHandler: (() -> Void)? = nil
func fetchUser(completion: @escaping () -> Void) {
completionHandler = completion
}
}
- 실행 순서 ▾
- 클로저가 fetchUser() 함수의 completion 인자로 전달이 됩니다.
- 클로저 completion이 completionHandler 변수에 저장이 됩니다.
- fetchUser() 함수가 값을 반환하고 종료됩니다.
- 클로저 completion은 아직 실행되지 않은 상태입니다.
- completion은 함수의 실행이 종료되기 전에 실행되지 않기 때문에 escaping closure(함수 밖)에서 실행되는 클로저입니다.
의문점 🤷🏻♂️
- Non-Escaping Closure에서도 @escaping이 붙어 있을 수 있는데, 모든 클로저 파라미터 타입에 @escaping을 붙여서 사용해도 되지 않을까?
의문에 대한 해답 📂
- 우선 나누어져 있는 이유를 알면 편합니다. ▾
- 컴파일러의 퍼포먼스의 최적화로 인해 나누어 사용을 한다.(Escaping Closure && Non-Escaping Closure)
- Non-Escaping Closure는 컴파일러가 클로저의 실행이 언제 종료되는지 알기 때문에, 때에 따라 클로저에서 사용하는 특정 객체에 대한 retain, release 등의 처리를 생략해 객체의 생명주기를 효율적으로 관리할 수 있습니다.
- Escaping Closure는 함수 밖에서 실행되기 때문에 클로저가 함수 밖에서도 적절히 실행되는 것을 보장하기 위해, 클로저에서 사용하는 객체에 대한 추가적인 참조 사이클 관리 등을 해줘야 합니다.
- 위의 부분에서 컴파일러의 퍼포먼스의 최적화에 영향을 끼치기 때문에 Swift에서는 필요에 따라 escaping closure를 사용하도록 구분해 두었습니다.
- 컴파일러의 퍼포먼스의 최적화로 인해 나누어 사용을 한다.(Escaping Closure && Non-Escaping Closure)
Escaping 이점 ▾
- 해당 클로저를 외부 변수/상수에 저장이 가능해집니다.
- 해당 함수가 끝나서 리턴된 이후에도 클로저 실행이 가능합니다.
그래서 왜 사용하는 건데??
예시 코드 ▾
func setImage(url: String) -> UIImage {
var image = UIImage()
Alamofire.request(url).responseImage { (response) in
if let image = response.result.value {
data = image
}
}
return data
}
예시 설명 ▾
- Alamofire.request는 비동기적으로 실행시킬 때, Alamofire의 완료 여부와 상관없이 따로 return data가 실행이 됩니다.
- return data가 실행되기 이전에 서버에서 이미지를 받아오는 부분이 안 끝나면 nil이 return이 됩니다.
- 이럴 때 @escaping closure를 사용하면 됩니다.
- 함수가 반환이 돼도 나중에 서버 작업 완료될 때 전달받는 것이 가능해집니다.
- 데이터를 수신에 대한 안전이 보장되는 형태가 형성이 됩니다.
'iOS_Swift.zip' 카테고리의 다른 글
[iOS]lazy 키워드 (0) | 2022.02.16 |
---|---|
[iOS]Frame과 Bounds의 차이 (0) | 2022.02.14 |
[iOS]SDWebImage 에러 (0) | 2022.02.11 |
[iOS]카카오 로그인(소셜) (0) | 2022.01.25 |
[iOS]면접 정리(1) (1) | 2022.01.20 |