Closure
코드에서 전달하고 사용할 수 있는 독립된 기능 블록
self-contained blocks of functionality이다. 다른 언어의 클로저, 익명 함수, 람다 및 블록과 유사하다.
// 일반적인 표현식
{ (<#parameters#>) -> <#return type#> in
<$statements#>
}
// closure: ascendingOrder
let ascendingOrder: (Int, Int) -> Bool = { (lhs, rhs) -> Bool in
return lhs < rhs ? true : false
}
let a = [4, 2, 3, 1]
let b = a.sorted(by: ascendingOrder)
print(b)
value capture
클로저의 주변 context의 상수와 변수를 capture 할 수 있다. 더 이상 존재하지 않더라도 클로저 본문 내에서 값을 참조하고 수정할 수 있습니다.
접근할 수 있는 상수와 변수들을 close over 한다.
incrementer
클로저는 total
과 incrementAmount
close over 한다.
내부에서는 변수들에 접근할 수 있으며, 호출될 때마다 상태가 유지된다.
total
은 클로저가 호출될 때마다 업데이트 되며, incrementAmount
는 클로저가 생성될 때 포착된 값을 유지한다.
func makeIncrementer(incrementAmount: Int) -> () -> Int {
var total = 0
let incrementer: () -> Int = {
total += incrementAmount
return total
}
return incrementer
}
let incrementByTwo = makeIncrementer(incrementAmount: 2)
print(incrementByTwo()) // 2
print(incrementByTwo()) // 4
closure는 참조 타입이다.
서로 다른 두 상수나 변수에 클로저를 할당하면 두 상수나 변수가 모두 동일한 클로저를 참조하게 된다.
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen() // returns a value of 50
incrementByTen() // returns a value of 60
escape closure
매개변수 유형 앞에 @escaping
넣으면 escape 한다고 말할 수 있다.
함수는 작업을 시작한 후 반환하지만 작업이 완료될 때까지 클로저가 호출되지는 않는다.
기본적으로 noescape 이며, 함수가 종료될 때 클로저도 함께 소멸됨을 의미한다. escaping 은 함수가 종료된 후에도 호출될 수 있다. 그렇기에 주로 비동기 작업에서 사용된다.
// noescape
func performOperation(operation: () -> Void) {
print("Performing operation")
operation()
print("Operation performed")
}
performOperation {
print("Hello, world!")
}
// Performing operation
// Hello, world!
// Operation performed
// escaping
func performAsyncOperation(completion: @escaping () -> Void) {
print("Starting async operation")
DispatchQueue.global().async {
sleep(2)
print("Async operation complete")
completion()
}
print("Async operation started")
}
performAsyncOperation {
print("Completion handler called")
}
// Starting async operation
// Async operation started
// (2초 후)
// Async operation complete
// Completion handler called
capture list
외부 변수나 상수를 capture 할 때 사용하는 메커니즘이다.
기본적으로 클로저는 강한 참조로 capture 한다.
매개 변수 앞에 대괄호로 둘러싸여 있으며, 순환 참조 문제를 해결하기 위해
self을 약한 참조로 캡쳐하도록 [weak self]
를 사용한다.
self 뿐만 아니라 여러 항목을 포함할 수 있다.
참고: implicit weak self capture
trailing closure
함수의 마지막 인수로 클로저 식을 전달해야 하는데 클로저 식이 긴 경우, 대신 후행 클로저로 작성하는 것이 유용할 수 있다.
한 줄에 인라인으로 작성할 수 없을 때 가장 유용하다.
func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
if let picture = download("photo.jpg", from: server) {
completion(picture)
} else {
onFailure()
}
}
loadPicture(from: someServer) { picture in
someView.currentPicture = picture
} onFailure: {
print("Couldn't download the next picture.")
}
'Language > Swift' 카테고리의 다른 글
새로워진 Swift 6 (WWDC24: What's new in Swift) (0) | 2024.06.19 |
---|---|
[Swift] Reactive Programming Combine - Resource (0) | 2024.05.29 |
[Swift] Reactive Programming Combine - Debugging (0) | 2024.05.19 |
[Swift] Reactive Programming Combine - Networking (0) | 2024.05.16 |
[Swift] Reactive Programming Combine - 7: Sequence (0) | 2024.05.16 |
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!