클로저(Closure)
인라인 함수
힙 메모리 안에 저장됨 → 기본적으로 참조 타입
클로저 내부에서는 그 주변에 있는 범위 안 모든 변수 참조 가능
지역변수를 넣은 클로저 중 하나에 지역변수 캡처하면 그 지역변수들 역시 보관되어야 함
클로저 안 캡쳐가 된 모든것들은 이미 힙 안에 있다면 클로저로부터 strong포인터를 갖고 아니면 힙으로 옮겨짐
객체가 클로저를, 클로저가 객체를 서로 가리킴 - 서로 strong 포인터를 가짐
힙을 벗어날 수 있는가? 포인터 중에 하나를 nil로 설정하지 않는 한 방법 없음
루트 연산 시 빨간색으로 디스플레이를 바꾸는 함수를 추가 예시
func addUnaryOperation(symbol: String, operation: (Double) -> Double)
//ViewController
addUnaryOperation("red√"){
self.display.test = UIColor.redColor()
return sqrt($0)
}
display 앞에 self를 넣는 이유
클로저가 self를 캡처 하고 영원히 strong 포인터를 유지(클로저가 살아있는 한)
클로저는 절대 힙을 떠나지 않는데 ViewController가 strong포인터를 가지고 있는 calculatorBrain에 있기 떄문임
ViewController→ calculatorBrain 참조
클로저(calculatorBrain)→ ViewController 참조
서로 순환참조 되고 있는데 어떻게 이 메모리순환 싸이클을 없앨 수 있을까?
→ weak, unowned 사용
addUnaryOperation("red√"){ [ unowned me = self ] in
me.display.test = UIColor.redColor()
return sqrt($0)
}
me는 클로저 안에서만 쓰이는 지역변수이고 값은 self
unowned는 참조횟수를 세지 않음 (self에 대한 strong 포인터 가지지 않음)
unowned는 조심해서 사용해야하는데 참조하고 있는 값이 오랫동안 지속되어야 함
만일 클로저가 viewController보다 메모리에 오래 남아 있으면 앱이 충돌(me가 메모리에 없는 것을 가리킴)
weak도 순환을 깰 수 있음
addUnaryOperation("red√"){ [ weak weakSelf = self ] in
weakSelf?.display.test = UIColor.redColor()
return sqrt($0)
}
클로저 안의 self는 ViewController?로 옵셔널 타입이 됨
여기서 self는 이름은 동일하지만 바깥에 있는 self와는 다른 변수임
옵셔널 체이닝 사용 필요하며 다른 이름으로 지정해줌(weakSelf)
'iOS > 스탠포드 iOS 강의' 카테고리의 다른 글
[스탠포드iOS] 프로토콜(Protocol) (0) | 2024.03.27 |
---|---|
[스탠포드iOS] 익스텐션(Extensions) (0) | 2024.03.27 |
[스탠포드iOS] 메모리 관리 (0) | 2024.03.25 |
[스탠포드iOS] ViewController 생명주기 (0) | 2024.03.25 |
[스탠포드iOS] Gestures (1) | 2024.03.22 |