티스토리 뷰

클로저(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에 있기 떄문임

ViewControllercalculatorBrain 참조

클로저(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)

최근에 올라온 글
Total
Today
Yesterday