티스토리 뷰

🍏/iOS

[iOS] subview reference strong vs weak

eungding 2021. 12. 4. 18:28
반응형

# Strong Subview Reference

 

Type 1 

class ViewController: UIViewController {

    private let someView: SomeView = SomeView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setupSomeView()
    }
    
    private func setupSomeView() {
        self.view.addSubview(someView)
        self.someView.snp.makeConstraints { maker in
            maker.width.height.equalTo(50)
            maker.center.equalToSuperview()
        }
    }
}

 

Type 2 

class ViewController: UIViewController {

    private var someView: SomeView?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setupSomeView()
    }
    
    private func setupSomeView() {
        let someView = SomeView()
        self.view.addSubview(someView)
        someView.snp.makeConstraints { maker in
            maker.width.height.equalTo(50)
            maker.center.equalToSuperview()
        }
        self.someView = someView
    }
}

 

Type 2 보다 Type 1 을 더 많이 쓰는 것 같아요.
특히 Then  을 쓰면 Type 1 코드를 깔끔하게 짤 수 있죠! 

 

# Weak Subview Reference

class ViewController: UIViewController {

    private weak var someView: SomeView?

    override func viewDidLoad() {
        super.viewDidLoad()
        setupSomeView()
    }
    
    private func setupSomeView() {
        let someView = SomeView()
        self.view.addSubview(someView)
        someView.snp.makeConstraints { maker in
            maker.width.height.equalTo(50)
            maker.center.equalToSuperview()
        }
        self.someView = someView
    }
}

 

# 차이점 

 

그럼 둘의 차이점은 무엇일까요?! 

subview 스스로 deallocated 될 수 있는가 없는가 에 대한 차이입니다. 

 

strong reference는 superview에 의해 유지되므로 subview가 스스로 deallocated 될 수 없습니다. 

반면 weak refernce는  subview가 스스로 deallocated 될 수 있습니다. 

 

subview.removeFromSuperView  를 해보면 위의 차이를 바로 알 수 있습니다. 

뷰컨트롤러에 아래 코드를 추가해서 테스트 해봅시다.  (subview 제거 버튼을 만들면 좋지만 귀찮으니...)

DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
    self.someView?.removeFromSuperview()
}

 

 

1. Strong Reference 

 

removeFromSuperView 후,  view hierarchy 에서 SomeView는 제거됩니다.

뷰에서도 확인가능 하고 lldb 로 출력해봐도 SomeView 가 없는 것을 볼 수 있어요. 

po self.view.value(forKey: "recursiveDescription")!

 

view hierarchy 에서 없어졌지만,  SomeView의 deinit은 불리지 않습니다.

ViewController가 deinit 될 때 SomeView의 deinit이 함께 불립니다. 

ViewController deinit
SomeView deinit

 

 

 

2. Weak Reference 

 

removeFromSuperView 후,  view hierarchy 에서 SomeView는 제거됩니다.

이 때 SomeView의 deinit이 바로 불립니다.  뷰컨이 들고 있는 someView 프로퍼티도 nil로 값이 바뀝니다. 

 

 

즉 정리해보면

✔️ Weak Reference - subview.removeFromSuperView  할 때, subview 의 deinit이 바로 불림. 

✔️ Strong Referecne - subview.removeFromSuperView 할 때, subview 의 deinit이 바로 안불림. superview가 deinit 될 때 subview 의 deinit 이 불림 

 

 

 

# 무엇을 선택해야할까?

사실 subview가 항상 view hierarchy에 있는 게 보장되면 strong, weak 둘다 상관없습니다. 

(항상 view hierarchy에 있다면 superview가 deallocated 되는 시점에 subview도 deallocated 되면 되는데, 둘다 그러니까!)

 

그럼  subview가 view hierarchy에서 사라지는 경우를 생각해봅시다.

 

첫번째는 일시적으로 view hierarchy에서 사라지는 경우 입니다. (예를들어 subview를 제거했다가 다시 추가하는 경우) 

이 때, strong reference로 subview를 hold 해서 일시 제거할 때 바로 deallocated 되는 것을 막을 수 있겠습니다. 

 

 

두번째는 아예 view hierarchy에서 사라지는 경우 입니다. 

이때는 subview가 바로 deallocated 되는게 더 자연스러우니  weak reference 를 써주면 되겠습니다. 

 

 

애플 staff 의 답변 참고해주세요! 

 

https://developer.apple.com/forums/thread/15082

 

 

[ Reference ]

 

https://developer.apple.com/forums/thread/15082

 

How to references a subview in an … | Apple Developer Forums

If your subview is always guaranteed to be in the view hierarchy, as it is in your code snippets, then whether your property is strong or weak won't make any difference. A strong reference will always be held by the superview so the subview will never be d

developer.apple.com

 

 

반응형
댓글