클로저는 정의된 둘러싸인 컨텍스트에서 상수와 변수를 캡처 (capture)할 수 있습니다. 그러면 클로저는 상수와 변수를 정의한 원래 범위가 더이상 존재하지 않더라도 본문 내에서 해당 상수와 변수의 값을 참조하고 수정할 수 있습니다.
Swift document: Closures
클로저 내부에서 외부의 값을 사용하기 위해, 해당 값을 클로저 내부적으로 저장하는 것
이것을 클로저에 의해 값이 캡처되었다‼️라고 함
캡처해서 가지고 있다가, 필요할 때마다 사용하는…!
이러한 정의를 이용해서 블럭을 해석해 보면,
클로저는 주변의 context에서 상수와 변수 값을 클로저 내부에 저장할 수 있다는 것.
여기서의 context는 클로저 주변의 함수와 같은 코드를 의미
예를 들어, 다른 함수 본문 내에 작성하는 중첩 함수는
바깥 함수의 인수와 바깥 함수 내에 정의된 상수와 변수를 캡처할 수 있음
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
incrementer()
함수를 포함하는 makeIncrementer(forIncrement)
함수를 정의하였다.
amount
파라미터에 전달된 인수 값은 makeIncrementer(forIncrement)
함수가 호출될 때마다 얼마나 증가시켜야 할지를 지정runningTotal
에 amount
만큼을 더하여 실제로 증가시키는 incrementer()
함수이때, runningTotal
과 amount
에 대한 참조를 캡처하기 때문에,
runningTotal
과 amount
가 사라지지 않고
다음 incrementer()
함수 호출 시에 해당 runningTotal
과 amount
를 사용함.
클로저도 reference type이기 때문에,
메모리에서 사라지는 순간까지 runningTotal
과 amount
는 계속해서 잡혀 있게 된다.
let incrementByTen = makeIncrementer(forIncrement: 10)
incrementByTen() // 10
incrementByTen() // 20
incrementByTen() // 30
이렇게 incrementByTen()
을 호출할 시에,
캡처한 runningTotal
을 계속해서 사용하는 것이다.
따라서 결과는 계속해서 10, 20, 30… 으로 증가하게 된다.
나는 runningTotal
을 참조해서 사용하고 싶지 않은데…
그냥 해당 값을 사용하고 싶은데… ,,,
이럴 때는 클로저의 캡처리스트를 사용하면 된다.
캡처리스트는 클로저에서 값이 캡처되는 방법을 명시적으로 제어할 수 있다.
in
키워드 앞에, [ ] 내에 넣어 작성var a = 0
var b = 0
let closure = {
print(a, b)
}
a = 10
b = 10
closure() // 10 10
var a = 0
var b = 0
let closure = { [a] in
print(a, b)
}
a = 10
b = 10
closure() // 0 10
a
를 캡처a
는 클로저가 생성될 때, 외부의 a
변수의 값으로 초기화됨a
가 변경되더라도 영향을 받지 않음a
를 변경하려 한다면?class TestClass {
var value = 0
}
var a = TestClass()
var b = TestClass()
let testClosure = { print(a.value, b.value) }
a.value = 10
b.value = 15
testClosure() // 10 15
class TestClass {
var value = 0
}
var a = TestClass()
var b = TestClass()
let testClosure = { [a] in
print(a.value, b.value)
}
a.value = 10
b.value = 15
testClosure() // 10 15
a
를 캡처했지만, value type capture은 되지 않음을 알 수 있음클로저 내부에서 주변의 context(환경, 코드… etc)의 값의 참조를 캡처하여 내부에서 사용할 수 있도록 하는 것을 캡처라고 한다.
캡처리스트에서는 이러한 캡처의 방식을 제어할 수 있는데,
캡처리스트에 value type 포함 시에 value type 캡처를 진행할 수 있다.
캡처리스트에서 reference type 포함 시에는 value type 캡처가 불가능하다.