본문 바로가기
Swift

ARC - Automatic Reference Counting

by HaningYa 2020. 8. 24.
728x90

 

 

ARC 란

Swift 에서 사용하는 메모리 관리 전략이다.

reference 숫자를 자동으로 counting 하여 메모리를 관리한다.

객체가 메모리에 할당될 때 reference를 저장하는 객체만 ARC의 영향을 받는다. 

그말은 reference type 만 ARC 의 관리를 받는 다는 뜻으로 구조체와 같은 value type은 메모리 관리 대상이 아니다

Reference type으로는 대표적으로 Class 와 Closure이 있다. 

자바의 메모리 관리 기술인 Garbage Collector 과 비교하자면 ARC는 컴파일 시간에 동작하고 GC는 런타임에 동작한다는 것이다.


ARC가 compile 타임에 동작하기 때문에

개발자는 ARC에게 메모리 leak 에 대비할 수 있도록 많은 힌트를 줘야 한다. 

reference의 종류에는 3가지가 있다.

  1. Strong
  2. weak
  3. unowned

Strong Reference 는 ARC의 default 값으로 따로 명시하지 않으면 strong 으로 참조된다. 해당 레퍼런스에 대한 강한 참조를 유지시키고 reference count를 증가시킨다.

하지만 Strong Reference 만 사용하면 Strong Reference Cycle (강한순환참조)가 일어날 수 있다.

강한 순환 참조

Class Person 과 Class Apartment 가 있고 서로 프로퍼티에 상대방의 Class 인스턴스를 가지는 Optional 한 변수가 있다고 생각 할때

인스턴스화 된 Person 인 john 과 Aparment 인 unit4A에 서로 각각의 인스턴스를 할당해 주면 위 그림과 같은 상황이 된다.

저 상태로 var john = nil 과 var unit4A = nil 을 하게되면 수직으로 연결된 strong reference count 는 감소되지만 Person instance 와 Apart instance 끼리 수평으로 연결된 strong reference 에 접근할 수 있는 방법이 없어진다. 즉 메모리 누수가 발생한다.

이 현상을 해결하기 위해 weak와 unowned가 있다.

weak 의 경우 해당 객체가 nil이 될 수 있음을 뜻한다. 항상 optional 로 선언되어야 하며 weak를 통해 생긴 인스턴스의 경우 reference count를 세지 않고 추후에 strong reference 가 해제되면 자동으로 weark reference 가 메모리에서 해제된다.

unowned 의 경우는 weak 와 비슷하지만 optional 이 아니라는 차이점이 있다. unowned 값이 무조건 있다는 가정하에 사용하기 때문에 nil이 되지 않는 확실한 상황일때 사용해야 한다.


Lazy 를 통해 객체가 초기화 된 후 사용하기 직전에 프로퍼티 값을 초기화 할 때 클로저가 변수에 대해 값을 획득하기 때문에 순환참조가 발생할 수 있다. 이때 self 를 통해 접근하는 경우 self는 값이 있음을 가정하므로 unowned self 를 통해 self 에 접근할 수 있다.
[출처]http://minsone.github.io/mac/ios/rules-of-weak-and-unowned-in-swift

내 생각엔 RxSwift 를 쓸때 unowned self 를 많이 봤는데 위 lazy 와 비슷한 맥락인 것 같다.

 //가입하기 버튼
        signInButton.rx.tap.do(onNext: {[unowned self] in
            self.emailTextField.resignFirstResponder()
            self.emailTextField.resignFirstResponder()
        }).subscribe(onNext: {[unowned self] in
            let SignInStoryboard = UIStoryboard(name: "SignIn", bundle: nil)
            let SignInVC = SignInStoryboard.instantiateViewController(identifier: "SignInVC")
            SignInVC.modalPresentationStyle = .popover
            self.present(SignInVC, animated: true, completion: nil)
        
        }).disposed(by: disposeBag)

 


참고

 

[Swift]weak와 unowned 사용 방법

강력 순환 참조(Strong Reference Cycle)를 벗어나기 위해 약한 참조(weak reference)와 미소유 참조(unowned reference)를 사용합니다. 이전 Objective-C를 사용할 때는 강력 참조와 약한 참조를 통해서 참조 계수(re

minsone.github.io

 

728x90

'Swift' 카테고리의 다른 글

Swift High Order Function Summary  (0) 2020.10.06
[DI] Initializer로 Swift 의존성 주입하기  (0) 2020.09.03
Swift: 프로퍼티와 메서드  (0) 2020.07.13
Swift: 구조체 vs 클래스  (0) 2020.07.13
Swift enum - 열거형  (0) 2020.07.09

댓글