티스토리 뷰

반응형

 

 


Resolving Strong Reference Cycles for Closures
클로져에 대한 강한참조순환문제 해결하기


당신은 클로져 정의의 일부로서 capture list를 정의함으로 서 클로져와 클래스 인스턴스 사이의 강한참조순환을 해결할 수 있습니다. capture list는 클로져 몸체 내부의 타입이 하나 혹은 두개 이상의 참조를 캡쳐할 때 사용 될 규칙을 정의합니다. 두 개의 클래스 인스턴스간의 강한참조순환과 같이, 당신은 각각의 캡쳐된 잠조들을 strong 참조 대신 weak 이나 unowned 참조를 사용할 수 있습니다.

weak참조를 사용할지, unowned 참조를 사용할지에 대한 적절한 판단은 당신의 코드의 각각의 파트 사이 관계에 따라 다를 수 있습니다.

참고 : Swift는 someProperty, someMethod() 대신 self 키워드를 앞에 명시하여 self.someProperty, self.someMethod등으로 사용하는 것을 권장합니다. 클로져 내의 self를 참조할때마다 말이죠. 이는 self에 의해 클로져캡쳐링, 강한참조순환이 발생할 수 있음을 자각시켜주기 때문입니다.

 

 

 


Defining a Capture List
캡쳐 리스트 정의하기


캡쳐 리스트(capture list)의 각각의 아이템은 weak / unowned 키워드 + self 참조변수 / 어떠한 값으로 초기화된 변수(delegate = self.delegate)의 쌍을 이룹니다. 이러한 쌍들은 클로져 블럭 안에서 작성됩니다. 각각의 쌍 사이에는 콤마(,)로 구분합니다.

만약 매개변수 리스트나 반환 타입이 존재한다면 이들을 정의하기 전에 캡쳐리스트를 배치해야합니다.


만약 클로져가 문맥적으로 유추가 가능할 수 있어 어떠한 특정 매개변수나 반환 값을 갖고 있지 않는다면, 해당 클로저 블럭 맨 시작부에 캡쳐리스트를 배치하고 뒤에 in 키워드를 붙여줍니다.


만약 클로져 내의 캡쳐가 클로져 참조 간 항상 참조가능함이 보장된다면 캡쳐에 unowned 참조를 정의하여 사용할 수 있습니다. 대조적으로 만약 캡쳐 변수가 nil이 될 가능성이 있다면, weak 키워드를 사용하여 캡쳐리스트에 정의할 수 있습니다. weak 참조들은 항상 옵셔널 타입이며, 참조하던 인스턴스가 해제될 경우 자동으로 nil이 될 수 있습니다. nil의 여부를 통해 당신은 클로져 내에서 해당 값이 존재하는지를 확인 할 수 있게 해줍니다.

참고 : 만약 캡쳐된 참조가 절대 nil이 될 일이 없다면, 이는 weak reference 보다는 unowned reference 로서 항상 캡쳐될 수 있습니다. 

 


미소유 참조는 앞서 보았던 클로저에 의한 강한참조순환으로 부터 HTMLElement 예시에서 이러한 순환참조를 해결할 수 있는 적절한 방법입니다. 아래 코드는 어떻게 HTMLElement 클래스가 순환문제를 해결하는지를 보여줍니다.

lazy 프로퍼티인 asHTML 클로져 변수 블럭 시작부에 캡쳐리스트가 추가된 것을 볼 수 있습니다. 


위의 코드는 이전의 HTMLElement 예시의 코드와 단 한가지 빼고 동일합니다. 바로 asHTML 클로져 안의 캡쳐리스트가 추가된 것을 제외하고 말이죠. 위 코드의 경우 캡쳐리스트는 [unowned self] 입니다. 이는 캡쳐한 self 를 강한참조 대신 미소유참조로서 참조하겠다는 것을 의미합니다.

당신은 HTMLElement 인스턴스를 이전 예시와 동일하게 아래와 같이 생성하고 출력할 수 있습니다.

HTMLElement 인스턴스를 참조 후 인스턴스 멤버 클로져인 asHTML을 실행하고 있습니다. 

 


아래 그림은 클로져 내에 캡쳐리스트를 사용함으로서 어떻게 인스턴스, 클로져 간 참조가 이루어지는지를 보여줍니다.

클로져가 self.text, self.name을 미소유 참조(unowned references)로서 참조하고 있습니다. 


현재 클로져 내 self의 캡쳐는 미소유 참조로 되어있습니다. 그러므로 HTMLElement 인스턴스가 캡쳐되었을 때 이를 강한참조로 잡고있지 않습니다. 이 경우 강한참조순환이 발생하지 않았으므로 paragraph 변수를 nil로 설정 했을 경우, 인스턴스는 정상적으로 해제됩니다. 그러므로 인스턴스의 소멸자 또한 정상적으로 호출되며 출력문구가 출력 됩니다.


캡쳐 리스트에 대한 더 자세한 정보가 궁금하다면, 캡쳐 리스트(Capture Lists) 관련 링크를 참조하세요.

 

 

 

지금까지 캡쳐리스트를 통해 클로져캡쳐링을 해결하는 방법을 다뤄보았습니다.
보통 개인적으로는 클로져캡쳐링 방지 목적으로 스위프트 코드를 작성할 때 안정성을 고려하여 [unowned self] 보다는 [weak self]를 많이 사용하는 것 같습니다.

여러분들은 어떻게 캡쳐리스트를 활용하시나요? 어떻게 순환참조를 방지하시나요?? 많은 의견 부탁드립니다. ^-^//

 

 


참고 문서 링크 ▼

Swift Automatic Reference Counting

 

반응형
댓글
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
글 보관함