-
[UIKit/스토리보드] IBOutlet weak & Collection은 왜 weak가 아닐까?Apple🍎/iOS 2024. 12. 30. 10:03
요새 Storyboard 기반으로 공부를 하다보니 “IBOutlet에 붙는 weak, 그리고 collection에는 왜 weak가 안붙는지?..”가 궁금해져서 찾아보게 됐다!
참조 관계 파악
View Controller를 살펴보면 아래와 같이 구성되어 있다.
View Controller > View > View 객체(UIImageView, UILabel,,,) 의 계층 구조로 설계되어있다.IBOutlet은 ViewController - View객체를 이어주는 연결을 하는데,
여기서 weak를 붙이는 이유는 아래와 같은 참조관계를 먼저 알아야한다.모든 ViewController는 View가 있어야하기 때문에, 강하게 참조한다.
- VC → View
그리고, View안에도 button, label 등 View 객체가 있어야하기 때문에 강하게 참조한다.
- View → View 객체
마지막으로 VIew Controller도 View 객체를 강하게 참조하는데…
왜냐하면 뷰객체들은 ViewController의 인스턴스 내부에 저장되는 것은 아니라 각 인스턴스(Button, Label,,)는 클래스로써 힙 영역에 저장된다.
그래서 IBOutlet으로 ViewController는 뷰 객체의 참조를 저장하게 된다.- VC → View 객체
위 그림대로 한다면, 결국 View객체의 Reference count = 2 이다.
(두개가 View 객체를 참조하고 있기 때문에)보통, View Controller를 없애면, VC → View, VC → View 객체 이 두개의 참조가 해제되기 때문에, 알아서 View, View 객체의 RC가 0이되면서 메모리에서 해제된다.
하지만 VC, View 전부 strong으로 강하게 참조하고 있어도, 순환 참조의 상황은 안발생하는데… 굳이 왜 weak를 권장하는 걸까?
weak를 사용해야하는 경우
하지만 어떤 경우 이 참조가 문제가 되냐면,,,,,
class ViewController: UIViewController { @IBOutlet var myView: MyView! // MyView는 View 객체 override func viewDidLoad() { super.viewDidLoad() // View 객체에서 ViewController를 참조할 때 weak 사용 myView.delegate = self } }
- 위와 같이 Delegate/target-action을 사용해서 View객체가 VC를 강하게 참조할 경우 → 순환참조 발생
- 이런 순환참조의 경우에 “메모리가 부족할 경우”
즉, 순환 참조를 갖고 있는 상태에서 메모리가 부족할 때 발생한다.
“didReceiveMemoryWarning”
메모리가 부족하면, didReceiveMemoryWarning 함수로 OS 단에서 필요없는 main view를 nil 처리하라고 권유 받는데… main view를 해제하면, sub view까지 모두 해제되는 동작을 하라는 것이다. (시스템이 자동으로 해제하진 않고, 경고를 통해 그렇게 권유받는다)
다만 여기서 IBOutlet strong으로 VC - View객체를 갖고 있다면,
view controller의 RC는 최소 1이하로 내려가지 않는다. (메모리 해제가 안됨)
마치 위에 서로를 strong으로 참조하고 있어서 안되는 것처럼…
그러므로 이러한 사태를 대비하기 위해 애초에 IBOutlet은 weak로 권장한다.
(사실 메모리가 부족한 경우가 많지 않기에, 자주 발생하진 않는다.)IBOutlet collection 에서는 왜 weak를 사용하지 않는가?
이 부분은 생각해보면, collection의 경우 배열인데,
배열은 구조체 형태이므로 힙 영역에 올라가지 않아, 메모리를 관리할 필요가 없다.
그래서 weak이니 strong이니 이런 참조 형태가 안붙는다.결론 & 참고 문헌
생각보다 찾아보면서, “순환참조이기에 당연히 메모리누수가 발생할 위험이 있다”라는 말이 써있는데,,
내가 생각하기엔 단방향 참조인데 왜 순환참조라고 하지? 라는 부분에서 시작해 찾아보다보니 계속 파게된 부분이었다.특히 didReceiveMemoryWarning 함수가 불려지면서 os단에서 view를 nil처리 한다고 한 부분도,실제로 강제로 nil 처리한다는 문서가 보이지 않아.. 블로그를 잘 보고 판단해야된다는 생각을 했다.
보통 사용자에게 그것을 구현하라고 권장하는 것이지 nil처리하는지는 잘 모르겠다.
(제가 못찾는거같아서.. 혹시 제대로 아시는 분 있으면 댓글로 남겨주세요🥹)참고 사이트
https://monibu1548.github.io/2018/05/03/iboutlet-strong-weak/
https://developer.apple.com/documentation/uikit/responding-to-memory-warnings
'Apple🍎 > iOS' 카테고리의 다른 글
[iOS]Pagination & CollectionView prefetchItemsAt 사용 (0) 2025.01.16 [UIKit] 뷰 생명주기(View Life Cycle) (0) 2025.01.02 [iOS] Kingfisher & AppStorage로 이미지 다운로드 속도 개선하기 (0) 2024.11.24 [SwiftUI] Hashable, Equatable, Identifiable (0) 2024.11.10 [iOS/SwiftUI] NavigationStack을 왜 사용하는가? (0) 2024.09.04