iOS 응용 (swift)
[iOS - swift] UIStackView의 removeArrangedSubview 사용시 주의사항 (메모리릭, Memory Leak)
jake-kim
2023. 5. 11. 01:15
UIStackView의 removeArrangedSubview
- 보통 UIStackView의 하위 뷰들을 제거할때 removeArrangedSubview를 통해 제거하는데, 이렇게만하면 memory leak이 발생
- subviews에 접근하여 명시적으로 해당 뷰에서 removeFromSuperview()를 호출해줘야 제거가됨
ex) 메모리 릭 확인을 위해, 메모리에서 해제된경우 deinit에서 print문을 호출하는 뷰 정의
class MyView: UIView {
init() {
super.init(frame: .zero)
backgroundColor = .yellow
NSLayoutConstraint.activate([
heightAnchor.constraint(equalToConstant: 200),
widthAnchor.constraint(equalToConstant: 200),
])
}
required init?(coder: NSCoder) {
fatalError()
}
deinit {
print("DEINIT: MyView")
}
}
- 사용하는쪽에서 이 뷰를 UIStackView의 addArrangedSubview()로 삽입
stackView.addArrangedSubview(MyView())
- 버튼을 눌렀을 때, removeArrangedSubview를 호출하는 코드를 놓고 이때 "DEINIT: MyView"가 호출되는지 확인
- 결과 -> DEINIT이 호출안되며, 메모리릭이 발생
@objc private func tap() {
stackView.arrangedSubviews
.forEach(stackView.removeArrangedSubview(_:))
}
- 만약 subviews에 접근하여 removeFromSuperview()를 호출시키면 DEINIT 프린트문 확인이 가능 (메모리해제 완료)
@objc private func tap() {
let subviews = stackView.arrangedSubviews
stackView.arrangedSubviews.forEach(stackView.removeArrangedSubview(_:))
subviews.forEach { $0.removeFromSuperview() }
}

- 공식 문서에서도 removeArrangedSubview()만 사용하면 뷰가 보일 수 있으니, 명시적으로 removeFromSuperview()를 사용하라는 문구가 존재

* 전체 코드: https://github.com/JK0369/ExStackView
* 참고
https://developer.apple.com/documentation/uikit/uiview/1622421-removefromsuperview