iOS

iOS) 강한 순환 참조(Strong Reference Cycle)는 어떤 경우에 발생하나요?

hyun99999 2023. 7. 12. 18:29
728x90
반응형

"인스턴스가 계속 사용되야 하기 때문에 메모리에 남아있어야 한다." 라는 명분을 주는 것이 Strong Reference(강한 참조)입니다.
레퍼런스 카운트가 증가될 때는 강한 참조인 경우에 해당합니다. 이 강한 참조는 별도의 식별자를 명시하지 않으면 강한 참조로 여겨집니다.

이때 어떤 상황에 대해서 클래스의 인스턴스의 사용이 끝났음에도 불구하고 레퍼런스 카운트가 0이 되지 않아 메모리에서 사라지지 않는 memory leak 이 발생하는 것을 강한참조 순환(strong reference cycle)이다.

언제 발생하나요?

  • 두 개 이상의 인스턴스가 서로를 강하게 참조하여 발생하게 된다.
    • 변수에 인스턴스를 할당하며 생기는 레퍼런스 카운트 이외에 서로가 참조하면서 레퍼런스 카운트가 추가로 증가. nil 을 할당하더라도 레퍼런스 카운트가 0이 되지 않게 된다.

  • 또한, view controller 와 collection view cell 버튼 액션과 같은 관계에서 delegate 를 사용하여 view controller 에 동작을 지정하는 것과 같을 때도 발생

class Cell: UICollectionViewCell {
    // ✅ 강한 참조가 발생하기 때문에 weak var 을 사용해야 함.
    var delegate: Delegate?

    // ...

    button.addTarget(self, action: #selector(touchAction), for: .touchUpInside)

    @objc func touchAction() {
         delegate.touch()
    }
}

class ViewController: UIViewController, TestDelegate {
    var cell: Cell?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // ...

        cell?.delegate = self
    }
    
    func touch() {
        // Cell 의 버튼 액션으로 view controller 에서 작업할 task 지정.
    }
}

protocol Delegate: AnyObject {
    func touch()
}
  • 변수뿐만 아니라 클로저와 관계해서도 발생하게 된다. 클로저에서 self 를 캡쳐하기 때문이다.(이때, 클로저 안에서 self 를 여러번 참조하더라도 실제로는 한 번만 참조된다.)
    • 변수에 nil 을 할당해도, 클로저에서 self 를 강한 참조하고 인스턴스가 클로저를 강한 참조하기 때문에 발생.

어떻게 해결하나요?

- 약한 참조, 미소유 참조를 사용하여 해결할 수 있습니다.

출처: https://jusung.gitbook.io/the-swift-language-guide/language-guide/23-automatic-reference-counting
  • 클로저에서 self 를 캡처하고, 약한 참조를 하게 되면 다음과 같이 파악할 수 있다.

  • guard let 구문으로 self 를 강한 참조하게 되면 다음과 같이 파악할 수 있다.

출처: https://phillip5094.tistory.com/65

728x90
반응형