non-Escaping Closure vs Escaping Closure
Swift에서 함수와 클로저는 일급 객체이다.
일급 객체라 함은 함수에 파라미터로 전달하고, 함수의 반환값이 될 수 있으며, 변수, 상수에 저장을 할수 있는 것을 의미한다.
non-Escaping Closure의 경우 클로저가 함수 본문을 탈출하지 않는다.
함수가 종료되기 전에 클로저가 실행된다는 것이다.
방금 위에서 말한 두 줄이 non-Escaping Closure와 Escaping Closure의 가장 큰 차이점이라는 것을 알아야 한다
그림으로도 대강 설명이 되있지만 흐름을 단계별로 써보자면..
- 함수 호출
- 클로저가 nonEscapeSquare 파라미터(completion)로 들어감
- 함수 내부에서 completion 실행
- completion이 값 반환하고 함수 종료
클로저가 함수가 종료되기 전에 호출이 되어 실행되는 것을 볼 수 있다.
그럼 뭘까??? nonEscapeClosure 인거임
더 확실한 차이를 알기위해서 하나 더 설명을 하자면!!
비동기에서 nonEscapeClosure를 실행할 경우를 보자..
비동기에서 nonEscapeClosure가 안되는 이유는 해당 클로저가 담긴 completion이 비동기로 실행되기때문에 종료 시점을 알 수가 없다.
전에도 알아봤지만 비동기는 그냥 DispatchQueue에 던져버리고 신경안쓴다고 그랬었다!! 그냥 일 처리 되든 말든 함수 종료 시킨다고..
비동기로 실행되는 nonEscapeClosure가 함수가 종료되고 실행이되므로 nonEscapeClosure는 함수 외부에서!! 함수가 종료되면!!!! 사용될 수 없다고 Escape로 바꾸라고 컴파일 오류가 뜨는 것이다
.
이제 확실히 알겠지..?
nonEscapeClosure는 함수 외부에서 사용 할 수 없!!!!다!!!!!!!!!
또한 메모리 관점에서도 설명할 것이 있는데..
nonEscapeClosure의 경우 함수의 호출과 종료에 따라 동일하게 실행되고 종료된다.
만일 클로저 내부에서 외부 상수나 변수를 참조한다면.. 참조할때 retainCount + 1, 함수가 종료되면서 -1 되므로 RC 문제가 없다.
class Test {
init() {
print(#function)
}
var testNum = 1
deinit {
print(#function)
}
}
func nonEscapeSquare(number: Int, comletion: (Int) -> ()) {
let resultNumber = number * number
comletion(resultNumber)
}
nonEscapeSquare(number: 3) { number in
let test = Test()
test.testNum += number
print(number)
print(test.testNum)
}
.. 네
위에서 escapeClosure까지 설명된 것 같긴한데 함더 살펴보자
위처럼 탈출 클로저로 만들게되면 해당 클로저를 외부 변수,상수에 저장할 수 있다.
그리고 클로저를 가진 함수가 종료되어도 클로저 실행이 가능하다. 외부에 저장하고 나중에 쓸 수 있으니깐 당연히 함수가 종료되어도 쓸수 있어야겠지?
위 이유가 가장 큰 차이이다.
대표적으로 escapeClosure가 사용되는 URLSession이다.
func makeRequest(_ completion: @escaping (Result<(Data, URLResponse), Error>) -> Void) {
URLSession.shared.dataTask(with: URL(string: "http://a.jollida/")!) { data, response, error in
if let error = error {
completion(.failure(error))
} else if let data = data, let response = response {
completion(.success((data, response)))
}
}
}
위 코드는 순서가 어떻게 될까?
dataTask의 클로저는 비동기로 네트워크 요청을 보내 응답이 오면 dataTask의 completion 함수가 호출되고, 내부에서 조건에 따라 makeRequest의 completion을 호출 하는 것이다.
더 설명을 못하겠다.
이게 다인 것 같아서.. 조만간 캡쳐나.. 탈출 클로저의 참조부분을 써봐야겠다.
'iOS > Swift' 카테고리의 다른 글
Swift) final (0) | 2022.02.20 |
---|---|
Swift) Frame vs Bounds (0) | 2022.02.20 |
Swift) Unit Test without networking (0) | 2022.02.20 |
Swift) GCD (Grand Central Dispatch) (0) | 2022.02.15 |
Swift) Main.sync 외 않됌? (1) | 2022.02.13 |
댓글