[Swift] Strong Reference Cycles: How to deal with it.

안녕하세요 :)

바로 이전 포스팅에서 ARC에 관한 이야기를 하면서

ARC 는 classinstance 가 생성될 때 ,해당 instancestrong reference를 생성하고, 그 것의 갯수를 Counting 한다는 내용을 다뤘는데요.

해당 내용을 다루고 있는 Swift 공식 Document 를 보면 아래와 같은 내용도 다루고 있습니다.

strong reference 가 ‘절대’ 사라지지 않는 경우가 발생할 수 있다.

두개의 class instance 가 서로에게 strong reference 를 갖고 있는 경우이다.

그것은 strong reference cycle’ 이라고 불린다.

strong reference cycle 은 어떻게 생겨날까요?

위와 같이 Car 과 ParkingLot 두가지 class가 있습니다.

여기서 아래와 같이 각 클래스 마다 instance를 생성해봅시다.

그럼 위와 같이 tesla variable 은 Car Class에, lot_3A variable은 ParkingLot Class에 strong reference가 생겼죠. 이제 여기에 두 instance간에 참조를 해봅시다.

자 이러한 경우에 Car instance 와 ParkingLot instance는 서로에게 strong reference 가 생기게 됩니다.
이러한 경우에 var tesla와 var lot_3A의 reference들을 깨버려도 먼저 언급했던 Car instance 와 ParkingLot instance strong instance는 없어지지 않는데요.

위 그림처럼 각 variable의 reference 들은 해소가 된 상태이지만,

각 instance들에 관한 것은 ‘strong reference cycle’ 이 되어 강력하게 남아있는 것을 확인할 수 있습니다.

strong reference cycle 은 어떻게 해결하는가

그렇다면 이러한 strong reference cycle 은 어떻게 해결할 수 있을까요?

이에 swift 공식 문서는 아래와 같이 답하고 있습니다.

Swift는 해당 문제에 대해 두가지 방법을 제시하고 있다

1. weak references

2.unowned references.

1. Weak Reference

weak referencestrong reference cycle 다른 한쪽이 더 짧은 수명을 가졌을 때, 즉 다른 한쪽이 메모리에서 더 먼저 지워질 상황에 사용합니다.

위 예시의 상황에서 생각해보면 자동차 보다는 주차장이 더 아무래도 수명이 길겠죠?

그러면 Car class 가 더 짧은 수명을 가졌으니, 아래와 같이 코딩을 해주면 됩니다.
문법은 var 앞에 weak 만 붙여주면 되는데요.

그렇게 되면 위와 같이 ParkingLot instance는 car에 대한 weak reference를 갖게 되고, 아래의 그림처럼 tesla 가 nil 값을 갖게 되면 두 instance 사이의 사이클은 해제가 되고 Car instance 인 tesla 도 메모리에서 해제가 되는 것이죠.

2. Unowned Reference

unowned reference weak과는 정반대로, strong reference cycle 의 다른 한쪽이 더 길거나 같은 수명을 가졌을 때, 즉 다른 한쪽이 메모리에서 더 나중에 혹은 동시에 지워질 상황에 사용합니다.

또 unowned 에는 weak과는 다른 차이점들이 있는데요.

  1. unowned는 언제나 값을 가진다는 점입니다.
  2. 따라서, unowned는 nil 이 될 수 없습니다.

이에 Swift 공식문서에서는 Important 라고 강조하며 이야기 하고 있는 것들이 있는데요.

Unowned는 반드시 사라지지 않을 instance일 때만 사용할 것

Unowned instance가 지워졌을 때 그 값에 접근하려고 하면 런타임 에러가 남

마찬가지로 위 두가지 class Citizen과 Identification을 보시죠.

위 예시는 weak의 예시와 명확하게 다른 부분은,
신분증은 시민없이는 생겨나지 않는 다는 것입니다.

따라서 Identification 와 비교했을 때, 당연히 또 반드시 Citizen의 수명이 더 길거나 같겠죠.

그리고 아래와 같이 instance 를 생성해줄 수 있습니다.

그리고 여기서 jay에 nil을 할당해주면, 두 instance들이 모두 deinit되게 됩니다.

해당 포스팅에 오류가 있다면 댓글로 알려주세요.

감사합니다 :)

--

--

iOS Developer 🇰🇷🇬🇧

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store