Closures - The Swift Programming Language (Swift 5.7)
클로저는 함수에 인수로 전달될 때 함수를 이스케이프한다고 말하지만 함수가 반환된 후에 호출됩니다. 클로저를 매개변수 중 하나로 사용하는 함수를 선언할 때 매개변수 유형 앞에 @escaping을 작성하여 클로저가 이스케이프할 수 있음을 나타낼 수 있습니다.
escaping 클로저는 매개변수로 받은 클로저가 함수 내부 스코프를 탈출해서 외부 쓰레드로 가는 것이다.
ex) 서버에 이미지를 비동기적으로 요청하고 반환하는 함수에서 escaping 클로저를 사용하지 않으면 empty 데이터를 반환하고 이미지가 업데이트 되지 않을 수 있다. 즉, 함수 내부에서 클로저의 사용이 끝난다는 말이다.
네트워크 요청 작업이 있을 때 비동기적으로 이를 처리하고 Task가 끝난 후 동작하는 것을 CompletionHandler에 명령하는 것이다.
statusCode == 200
의 조건을 만족했을 경우
completion(.success(”object”))
로 선언하는 것은 통신이 성공했으니 200에 맞는 데이터를 넣어주고 escaping closure를 실행하라는 의미이다. 만약 실패했을 경우 completion(.failure(error))
func requestData(with url: URL,
completion: @escaping (Result<Data,APIError>) -> Void) {
session.dataTask(with: url) { data, response, error in
guard error == nil else {
completion(.failure(.unknownErrorOccured))
return
}
guard let response = response as? HTTPURLResponse,
(200..<300).contains(response.statusCode) else {
completion(.failure(.invalidURL))
return
}
guard let verifiedData = data else {
completion(.failure(.emptyData))
return
}
completion(.success(verifiedData))
}.resume()
}
매개변수로 불러온 클로저를 해당 함수에서 사용하는 것은 전혀 문제가 되지 않는다.
하지만 이 클로저를 저장하고 다른 곳에서 호출하려고 한다면 컴파일 에러가 발생한다. 이를 다른 곳에서 사용 가능하도록 만들기 위해선 @escaping
키워드를 사용해 탈출 클로저를 만든다.