iOS/Swift

[Swift] Strong, Weak, Unowned 참조

HarryJeonn 2022. 12. 5. 17:52

Strong

해당 인스턴스의 소유권을 가진다.

자신이 참조하는 인스턴스의 retain count를 증가시킨다.

값 지정 시점에 retain이 되고 참조가 종료되는 시점에 release가 된다.

선언할 때 아무것도 적어주지 않으면 default로 strong 참조가 된다.

var strongRef: StrongRef? = StrongRef() // retain count 1 증가
strongRef = nil // retain count 1 감소하면서 0이 되어 메모리 해제

Weak

해당 인스턴스의 소유권을 가지지않고, 주소값만 가지고 있는 포인터 개념이다.

자신이 참조하는 인스턴스의 retain count를 증가시키지 않는다. (release도 발생하지 않는다.)

자신이 참조는 하지만 weak메모리를 해제시킬 수 있는 권한은 다른 클래스에 있다.

메모리가 해제 될 경우 자동으로 레퍼런스가 nil로 초기화 해준다.

weak 속성을 사용하는 객체는 항상 optional 타입이여야 한다. (해당 객체가 nil일 수 있기 때문이다.)

weak var weakRef = WeakRef() // weak 속성을 사용하기 때문에 객체가 바로 해제되어 nil이 된다.

Unowned

해당 인스턴스의 소유권을 가지지 않는다.

자신이 참조하는 인스턴스의 retain count를 증가시키지 않는다.

nil이 될 수 없다. optional로 선언되어서는 안된다.

unowned var unownedRef = UnownedRef() // 객체 생성 후 바로 해제되어 댕글링 포인터만 가지고 있다. 에러난다.

댕글링 포인터는 해제된 메모리 영역을 가리키고 있는 포인터를 의미한다.

Weak vs Unowned

weak는 객체를 계속 추적하면서 객체가 사라지게 되면 nil로 바꾼다.

unowned는 객체가 사라지게되면 댕글링 포인터가 남는다.

이 댕글링 포인터를 참조하게 되면 에러가 나기 때문에 unowned 참조는 사라지지 않을 것 이라고 보장되는 객체에만 설정해야한다.

언제 사용하는가 ?

Strong

Reference count를 증가시켜 ARC로 인한 메모리 해제를 피하고, 객체를 안전하게 사용하고자 할 때 쓰인다.

Weak

대표적으로 retain cycle에 의해 메모리가 누수되는 것을 방지하기 위해 사용되며 Delegate 패턴이 있다.

Unowned

객체의 라이프사이클이 명확하고 개발자에 의해 제어 기능이 명확한 경우, weak optional 타입 대신 사용하여 좀 더 간결한 코딩을 할 수 있다.

약한 참조가 필요한 경우 weak 키워드를 사용하여 optional binding을 통해 안전하게 사용하는 것을 권장한다.