새소식

iOS/Swift

캡쳐리스트

  • -

그동안 수없이 사용했던 캡쳐리스트에 대해 오해하고 있었던 것 같아서 다시 정리한다.

  1. 클로져를 사용할 때 같은 컨텍스트에 있는 변수들을 캡쳐리스트 없이 사용하게 되면 reference type이든, value type이든 무조건 reference로 캡쳐된다.
  2. 캡쳐리스트를 사용하면 value type은 클로져 생성 시의 값을 그대로 복사하여 value를 캡쳐할 수 있다.
  3. 단 reference type은 캡쳐 리스트를 사용해도 reference로 캡쳐가 되기 때문에 weak, unowned 를 사용하여 retain cycle을 피할 수 있도록 해야 한다. 명시하지 않으면 strong 캡쳐가 기본이다.

3번은 익히 잘 알고 있는 내용이고 1, 2번에 의하면 self가 struct 이더라도 캡쳐리스트에 명시하지 않으면 reference 로 참조된다는 사실을 기억해야겠다. 그런데 그렇다고 해도 struct인 self를 value 캡쳐해야할 상황이 있을지는 잘 모르겠다. self 보다는 특정 변수에 대해서 그런 니즈가 생길 수는 있을 것 같다.

 

그러면  DispatchQueue에 넘기는 클로져에는 캡쳐리스트를 사용해야 하는가? 결론부터 말하면 상황에 따라 다르다는 것이다. 일단 DispatchQueue에서 클로져를 넘겨받는 객체는 일반적으로 static 프로퍼티(main)이거나 static 함수(global())이기 때문에 self로부터 큐에 대한 참조가 발생하지 않아서 순환참조에 대해서는 자유롭다. 커스텀 큐를 만들어서 self가 참조한다고 해도 큐에서 작업이 끝나면 참조가 사라지기 때문에 일반적으로 문제가 되지 않을 가능성이 높다.

DispatchQueue에서 캡쳐리스트를 명시적으로 사용해야 하는 이유는 self가 해제된 이후에도 작업이 끝까지 완료될 필요가 있는가이다. 이 질문에 대한 답이 yes 라면 strong 캡쳐(암시적 캡쳐리스트 포함)를 사용해야 하는 것이고 그렇지 않다면 weak/unowned 캡쳐를 사용해야 할 것이다. 전자의 경우 self 객체의 수명은 클로져의 작업이 완료될 때까지로 늘어날 수 있다. 파일 다운로드 등의 백그라운드 작업을 수행한다면 전자의 방법을 사용할 수 있겠지만, 화면 업데이트 작업에서는 굳이 strong 캡쳐를 사용하여 self 객체의 수명을 불필요하게 늘릴 필요는 없을 것이다. 그러나 또 화면 업데이트가 통상적으로 그리 오래 걸리는 작업이 아님(여기서 통상적이라고 말한 이유는 오래걸리는 작업을 한 후에 화면을 업데이트 하는 경우는 예외이고 추천하는 방식도 아니기 때문이다.)을 감안한다면, 화면 업데이트 작업인 경우에 한해 [weak self]를 추가하는 것은 권장사항 정도가 될 수 있을 것 같다.

비슷한 논리로 UIView.animate() 함수에 넘기는 클로져에 대해서도 생각해볼 수 있다. 애니메이션이 모두 끝난 후에 화면(self 객체)이 사라져야 하는 경우라면 self 객체의 수명을 늘려야 할 이유가 충분할 것이다. 그러나 역시 애니메이션 도중이라도 화면이 빨리 사라지는 게 더 중요하다면 weak/unowned 캡쳐를 사용해서 self 객체를 제 때 죽을 수 있게 내버려 둘 수도 있다. 

 

참고

https://skytitan.tistory.com/496

 

[Swift] 캡처리스트 (Capture List)

Closure - Capture List 주변 환경의 범위에서 참조한 변수들을 얼마나 강하게 캡쳐해야하는지를 명시하는 것으로, 캡쳐리스트를 사용하여 메모리 누수를 일으키는 강한 참조 순환을 피할 수 있게 된

skytitan.tistory.com

https://gyuios.tistory.com/220

 

iOS) DispatchQueue에서 [weak self] 를 사용해야만 하나요?

좀 더 근본적인 질문을 던져보자. ✅ DispatchQueue 에서 strong reference cycle(강한 참조 순환) 은 발생할 수 있는가? 라는 질문에 대해서 결론적으로는 변수로 저장하지 않으면 강한 참조 순환이 발생하

gyuios.tistory.com

반응형
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.