오늘은 또 네트워크 TCP 통신관련 프로젝트를 만들다가 신기한 경험을 했습니다... 사용하지 않는 뷰의 메모리 할당해제 관련 주제입니다.
side menu는 잠깐 들어가는 것이고 메인 뷰와 사이드 뷰 둘 다 뷰로 구현했습니다. 그래서 일반적으로 sideView를 보여줘야할 경우에만 인스턴스를 할당하고 hide될 때 해제를 했습니다.
sideMenu는 옵셔널로 할당했습니다. 그리고 showSideMenu라는 함수를 실행할 때마다 인스턴스 할당을 했습니다.
저 setLayout함수안에서 view.addSubview(self)를 진행합니다.
hideSideMenu에서는 화면 전환 애니메이션 로직을 모두 실행한 이후에 sideMenu = nil처리를 해서 MessageListViewController 내부에 인스턴스 해제를 실행하게 했습니다. 혹시나 하는 마음에 view herarchy를 봤는데,,,
여전히 남아있었네요 :) 분명 nil처리를 했는데...
그래서 view의 함수인 addSubview(_:)를 살펴봤습니다. 진짜 많이 사용했는데,, 귀찮아서 나중엔 subview를 배열로 묶어 map으로 처리를 하긴 하고 있지만... 그럼에도 이 함수의 설명을 이제서야 공식문서에서 찾아 봤습니다.
subview의 superView는 단 하나여야하고,, 무엇보다 strong reference를 한다고 합니다..... ㄷㄷㄷ
그럼 당연히 viewController에 있는 sideMenu view와 view.addSubview를 통해 추가 됬기에 view의 subviews에는 여전히 sideMenu가 남아있습니다. .. sideMenu가 참조되서 참조카운트가 1 증가합니다.,,,, sideMenu가 nil처리될 경우 참조카운트가 0이되어서 viewController에서는 할당 해제되지만, subviews에는 참조된 상태이기 때문에 ( UIView는 클래스타입 ) 여전히 subviews에 해당 정보가 남아있게 됩니다. ㄷㄷ 결국 vc에서 nil처리 말고 view's subviews에서 하나 더 해줘야 한다는 것입니다.
이 문제를 해결하기 위해서는 185라인의 nil이 뿐 아니라 subveiw로부터도 제거해 줘야합니다. 그 함수가 바로 removeFromSuperview() !!!!!
event 응답 체인, 윈도우와 자신의 superview로부터 Unlink가 됩니다. 참조중인 subview를 superview로부터 지우는 함수입니다. 뷰 계층에서 분리가 됩니다. ( superview로부터 지워졌기 때문입니다.) 하지만 superview의 subviews [UIView]에서만 제거가 된 것이기 때문에 여전히 viewController의 sideMenu 인스턴스는 남아져 있습니다. 그래서 185번 라인을 통해 완전히 인스턴스를 해제할 수 있습니다.
그 결과 몇번을 showSideMenu(), hideSideMenu()해도 완전히 지워지게 됩니다.
'iOS > Deep dive!!!' 카테고리의 다른 글
[iOS] UnitTest?! 테스트 코드를 짜면 좋은 이유 | Protocol을 통한 의존성 주입+역전 개념 완전 뿌수기 (0) | 2023.07.13 |
---|---|
[Test] xcode 14.3에서 code coverage 설정하는 방법 (0) | 2023.06.29 |
[iOS] UITextField 입력시 자동으로 키보드 띄우기, 키보드 위에 버튼 올리기 +_+ | InputAccessoryView (1) | 2023.05.30 |
[iOS] UITextField placeholder 색 변경하는 방법 (2) | 2023.05.30 |