함수에 전달하는 클로저는 자체 매개변수를 받을 수도 있습니다.
클로저를 함수를 호출할 때 작성해줘서 함수에서 사용
func travel(action: (String) -> Void) {
print("I'm getting ready to go.")
action("London")
print("I arrived!")
}
travel { (place: String) in
print("I'm going to \(place) in my car")
}
// 실행결과
I'm getting ready to go.
I'm going to London in my car
I arrived!
함수에 전달하는 클로저는 반환값을 지정할 수 있습니다.
반환하는 클로저를 함수를 호출할 때 작성해줘서 함수에서 사용
func travel(action: (String) -> String) {
print("I'm getting ready to go.")
action("London")
print("I arrived!")
}
var result: String = ""
travel { (place: String) -> String in
result = "\(place)도착"
return result
}
print(result)
// 실행결과
I'm getting ready to go.
I arrived!
London도착
반환값이 있는 클로저를 사용하는 예제 - reduce()
함수에 선언한 클로저매개변수가 명확할 경우 후행클로저에서 매개변수를 생략할 수 있습니다.
func travel(action: (String) -> String) {
print("I'm getting ready to go.")
let description = action("London")
print(description)
print("I arrived!")
}
travel { (place: String) -> String in
return "I'm going to \(place) in my car"
}
// MARK - 매개변수가 String인 것을 알기 때문에 생략 가능
travel { place -> String in
return "I'm going to \(place) in my car"
}
// MARK - 반환값이 String인 것을 알기 때문에 생략 가능
travel { place in
return "I'm going to \(place) in my car"
}
// MARK - 반환하는 코드가 한줄이므로 return 생략 가능
travel { place in
"I'm going to \(place) in my car"
}
// MARK - 매개변수자체 생략 가능
travel {
"I'm going to \($0) in my car"
}
스위프트는 클로저를 작성할 때 매개변수를 단축인자이름을 제공합니다.
클로저구문은 자동으로 매개변수 이름에 $0, $1, $2
등등 단축인자이름을 제공합니다.
단축인자는 모든 타입을 제공합니다.
❗️ 매개변수명을 지정한 경우 단축인자와 같이 사용하면 에러가 발생합니다.
$0
의 의미를 쉽게 이해할 수 있어서 편리합니다.$0
단축인자가 여러번 사용되는 경우 주의합니다.클로저에 여러매개변수를 추가할 수 있습니다.
클로저는 많은 매개변수를 사용할 수 있지만, 일반적으로 0 ~ 3개의 매개변수를 자주 사용합니다. 그 결과, $0, $1, $2
까지 이해하기 편립한다.
func travel(action: (String, Int) -> String) {
print("I'm getting ready to go.")
let description = action("London", 60)
print(description)
print("I arrived!")
}
travel {
"I'm going to \($0) at \($1) miles per hour."
}
함수에서 반환된 클로저를 가져올 수 있습니다.
->
를 두번사용합니다. 한 번은 함수의 반환 값을 지정하고 두번 째는 클로저의 반환값을 지정합니다.
func travel() -> (String) -> Void {
return {
print("I'm going to \($0)")
}
}
let result = travel() // (String) -> () 타입 클로저반환
result("London") // 클로저에 매개변수 선언
let result2 = travel()("London") // 한번에 사용
함수에서 클로저를 반환하면 안에서 일어나는 기능에 대해서 자세히 알지 않아도 되는 이점이 있고 필요할 때마다 함수전체를 수정하지 않고 클로저를 수정할 수 있습니다.
https://www.hackingwithswift.com/quick-start/understanding-swift/returning-closures-from-functions
How Do I Declare a Closure - 클로저 구문
클로저 내부에서 외부 값을 사용하는 경우 스위프트는 이 값을 캡처합니다. 클로저와 함께 저장하므로 수정할 수 있습니다.
func travel() -> (String) -> Void {
var counter = 1
return {
print("\(counter). I'm going to \($0)")
counter += 1
}
}
let result = travel()
result("London")
result("London")
result("London")
result("London")
// 실행 결과
1. I'm going to London
2. I'm going to London
3. I'm going to London
4. I'm going to London
캡처 기능이 있는 이유가 뭘까?
캡처기능이 있어서 클로저가 작동하는 데 필요한 데이터에 접근할 수 있습니다.
예를 들어 앞 뒤 번호가 같은 경우 겹치는 값이 안나오게 하려고 하는 경우
// MARK - 원하는 값이 나오지 않고 겹쳐서 난수 발생
func makeRandomNumberGenerator() -> () -> Int {
return {
var previousNumber = 0
var newNumber: Int
repeat {
newNumber = Int.random(in: 1...3)
} while newNumber == previousNumber
previousNumber = newNumber
return newNumber
}
}
let generator = makeRandomNumberGenerator()
for _ in 1...10 {
print(generator(), terminator: "")
}
// 실행결과
2312232333
→ var previousNumber = 0
을 클로저 외부에서 캡처해서 사용하도록 하면 반복해서 0이 저장되지 않기 때문에 겹치지 않는 결과가 나타납니다.
https://alisoftware.github.io/swift/closures/2016/07/25/closure-capture-1/