[iOS] Capture Value

Eugenie·2022년 7월 26일
0

📸 Capture

Swift 공식문서에 다음과 같은 구문이 있다.

A closure can capture constants and variables 
from the surrounding context in which it's defined.

클로저는 주변의 컨텍스트에 있는 상수나 변수들을 캡쳐할 수 있다.

상수와 변수를 정의한 원래 범위가 더 이상 존재하지 않더라도
그 상수와 변수의 값을 참조하고 수정할 수 있다.

🪺 Nested Function

Swift 에서 값을 캡쳐할 수 있는 클로저의 가장 간단한 형태는
중첩함수 [ Nested Function ] 이다.
이는 다른 함수의 body 안에 정의되어 있다.

중첩 함수는 외부 함수의 인수를 캡쳐할 수 있으며
또한 외부 함수 내에 정의된 상수와 변수를 캡쳐할 수 있다.

// example1
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount // runningTotal과 amount를 캡처
        return runningTotal
    }
    return incrementer
}

내부의 incrementer 함수는
변수 runningTotalamount 의 값을 캡쳐하고 있다.

이 값들을 캡쳐한 후, incrementer 함수가 호출될 때마다
runningTotalamount 값을 더하여 반환하는 클로저로,
makeIncrementer 의 반환 값으로 사용되고 있다.

함수 makeIncrementer 는 반환타입이 () -> Int 이다.
이는 함수를 반환한다는 것을 의미한다.
반환되는 함수는 매개변수가 없으며 호출될때마다 Int 값을 반환한다.

만약 위의 중첩형태를 중첩하지 않는다면 어떻게 될까?

// example2
func incrementer() -> Int {
	runningTotal += amount
    return runningTotal
}

함수 incrementer 에 아무런 매개변수가 없기 때문에
변수 runningTotalamount 는 참조값을 캡쳐한 것이다.

참조값을 캡쳐한다는 것은 함수 makeIncrementer 가 종결되어도
함수 incrementer 가 다음에 또 호출되더라도
변수 runningTotalamount 의 값은 사라지지 않는다는 것을 보장한다.

Swift 는 해당 값이 클로저에 의해 변형되지 않고
클로저가 생성된 후에 값이 변형되지 않는다면
값의 복사본을 캡쳐하여 저장할 수 있도록 최적화되어 있다.

❗️ Points to note

만약 클래스 인스턴스의 프로퍼티로 클로저를 할당하고
해당 인스턴스 또는 해당 인스턴스의 멤버 변수들을 참조하여
해당 인스턴스를 캡쳐하는 경우,
클로저와 인스턴스 사이에 강한 참조 사이클이 발생한다.

Swift 는 캡쳐 목록을 이용하여 강한참조를 해제한다.


📚 Reference
Closures
Swift: Closure와 Capturing
[Swift] Capturing Values 값을 캡쳐한다는 것

profile
🌱 iOS developer

0개의 댓글