일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- JavaScript
- 자바스크립트
- git
- 코드트리
- Apple Developer Academy
- AppleDeveloperAcademy
- 프로그래머스
- velog
- ios
- UIKit
- Xcode
- 프로젝트
- 코딩테스트실력진단
- 프론트엔드
- SWIFT
- 회고
- 코드트리챌린지
- 알고리즘
- swiftUI
- react
- tshaped
- 코딩테스트
- react-query
- frontend
- iOSDeveloper
- error
- Front-end
- NextJs
- globalcommunity
- TypeScript
- Today
- Total
Moon Work
[Swift] @escaping 키워드와 클로저 본문
시작하며
javascript라는 법이 없는 나라에서 온 나는 Swift의 @escape 키워드가 당황스럽고 또 놀랍다. @escape는 클로저를 인자로 전달받는 함수 내부에서 외부로 클로저를 전달하는 경우(비동기 등으로 클로저를 전달 받았을 때) 사용하는 키워드이다. 어떤 경우에 사용하는지 알아보자.
escaping-closure and non-escaping-closure
A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write
@escaping before the parameter’s type to indicate that the closure is allowed to escape.
escaping-closure는 인자로 전달받는 closure를 함수 외부에 할당하거나 함수가 종료된 이후에 사용하는 경우에 사용한다. 기본적으로 클로저는 non-escaping 클로저이기 때문에 다른 함수에 인자로 전달해주거나 클로적를 저장해 두고 사용하기 위해서는 closure를 받는 인자 앞에 @escaping 키워드를 붙여주어야 한다.
class Weather {
var completion : (() -> Void)?
func getWeather(completionHandler: @escaping () -> Void){
completion = completionHandler
}
}
escaping-closure와 weak self
closure는 context capture를 통해 클래스의 인스턴스를 참조한다. 따라서 @escaping 을 통한 클로저에 인자로 클로저를 보내는 경우 순환 참조(ARC)를 통한 메모리 누수가 발생할 가능성이 있다.
위와 같은 순환참조를 막기 위해 [weak self]를 통해 인스턴스에 대한 약한 참조를 함으로 순환참조를 대비할 수 있다. 예시를 통해 확인해보자.
final class WeatherManager {
static let shared = WeatherManager()
private init() {}
typealias NetworkCompletion = (Result<WeatherData, NetworkError>) -> Void
//⭐️ @escaping으로 다른 함수로 전달 가능한 escaping-closure로 변환
func getWeatherInfo(completion: @escaping NetworkCompletion){
let urlString = "\(WeatherAPI.requestURL)\(WeatherAPI.params)&appid=\(SecretKey.apiKey)"
performRequest(urlString: urlString,completion: completion)
}
...
}
...
func setupData(){
var weatherInfo: String?
//⭐️ weak self ⭐️를 통한 약한 참조
weatherManager.getWeatherInfo { [weak self] result in
switch result {
case .success(let weatherData):
self?.weatherInfo = weatherData.weather[0].main
case .failure(let error):
print(error.localizedDescription)
}
}
}
getWeatherInfo라는 함수를 통해 클로저를 전달하는데 weak self 키워드를 통해 약한 참조를 통해 보내고 @escaping 키워드를 통해 받은 클로저를 다른 함수의 인자로 다시 보낼 수 있게 할 수 있었다.
References
https://docs.swift.org/swift-book/documentation/the-swift-programming-language/closures/
Documentation
docs.swift.org
https://velog.io/@parkgyurim/Swift-escaping-closure
[Swift] @escaping 클로저
📚 Swift @escaping 클로저에 대해 알아보자
velog.io
'Swift' 카테고리의 다른 글
[Swift] \. 는 무엇인가 (KeyPath 정리) (0) | 2023.03.23 |
---|---|
[Network] URL로 네트워크 요청하기 (0) | 2023.03.12 |
[Swift] 메모리 참조 strong, weak, unowned 비교 (0) | 2023.02.09 |
[Swift] Swift 기본 문법 정리 5: Property (0) | 2023.02.01 |
[Swift] Swift 기본 문법 정리 4: Protocol 📑 (0) | 2023.01.30 |