들어가며
셀 안의 버튼을 클릭했을 때 클로저로 처리하고 싶어 방법을 찾아보던 중 발견한 코드들에 [unowned self] 키워드가 붙은 것을 보았고, 비슷한 키워드인 [weak self]도 생각나 궁금해져 공부해보고 정리하게 되었습니다 ...
ARC란 무엇인가?
Automatic Reference Counting의 줄임말입니다.
직역하자면 자동 + 참조 + 카운팅
자세한 정의는 이렇습니다.
1. Swift에서의 메모리 관리 방식이며, 객체에 대한 참조 카운팅을 관리합니다.
- 카운팅이 0이 되면 자동으로 메모리를 해제시킴 (→ 이를 deinit이라고 함)
2. 컴파일 시간에 (= 빌드할 때) 실행되어 retain과 release를 적절한 위치에 삽입해줍니다.
- retain, release는 객체의 유지와 감소를 말함
컴퓨터에는 네 가지 메모리 영역이 존재하는데요! (Data / Heap / Stack / Code)
여기서 참조형 자료들 (대표적으로 class와 closure가 있죠?)은 Heap에 속하며 동적으로 할당됩니다.
동적으로 할당되면 시간적인 측면에서 효율성이 좋아지지만, 따로 관리를 해줘야 하는 번거로움이 생깁니다.
ARC는 Heap 영역 (= 메모리)에 참조되는 객체들을 counting 횟수에 따라 자동으로 관리 (= 할당 & 해제) 해줍니다.
Retain Cycle
하지만 할당과 해제가 제대로 되지 않는다면, 메모리 누수가 발생하게 됩니다.
(→ 앱에서 사용하는 메모리 용량이 늘어나고, 크러쉬 발생 가능성이 높아짐)
ARC가 제대로 동작하지 않아 도움을 주어야 하는 이러한 상황을 Retain Cycle이라고 하는데요,
여기에 대한 해결법 두 가지가 바로 weak reference, unowned reference인 것입니다!
1. weak reference (약한 참조)
- 참조가 인스턴스를 방해하지 않겠다는 의미입니다.
- 옵셔널 타입으로, 할당이 제거되면 (= 참조하고 있는 인스턴스가 메모리에서 해제가 되면) ARC는 nil로 참조값을 대체합니다.
- 참조하고 있는 객체의 생명 주기가 짧은 경우에 사용합니다.
2. unowned reference (미소유 참조)
- weak와 비슷하지만, 옵셔널이 될 수 없다는 점이 다릅니다. (= nil이 될 수 없음)
- 때문에 사용 시 인스턴스가 메모리에서 해제된 이후 다시 접근하지 않을 확신이 있는 변수에만 붙여줍니다.
활용
[weak self], [unowned self]
→ 클로저의 강한 순환 참조를 막기 위해 사용되는 캡쳐 리스트입니다.
캡쳐 리스트란?
- 클로저 안에서의 참조 타입을 정의하는 리스트
강한 순한 참조란?
- retain cycle을 발생시키는 중첩된 참조 구조
- 예시 → 뷰 컨트롤러가 컬렉션 뷰를, 컬렉션 뷰가 컬렉션 뷰 셀을, 컬렉션 뷰 셀이 클로저를 소유하는 상황
저는 셀 안의 버튼을 클릭했을 때 알랏창을 띄우기 위해 셀에 클로저 변수를 만든 다음 함수에 넣어두고, 뷰 컨트롤러의 cellForItemAt에서 불러와서 사용을 해줬는데요! 여기서 [unowned self]가 사용되었습니다.
cell.accept = { [unowned self] in
let alert = UIAlertController(title: "지민지민님이 캘린더 공유를 요청했어요", message: "수락하면 상대방이 지안님의 캘린더를\n볼 수 있어요!", preferredStyle: .alert)
let refuse = UIAlertAction(title: "취소", style: .default, handler: nil)
let accept = UIAlertAction(title: "확인", style: .default, handler: nil)
[refuse, accept].forEach {
alert.addAction($0)
}
self.present(alert, animated: true)
}
[unowned self]나 [weak self]를 붙여주지 않고 그냥 [self]를 사용한다면, 클로저에서 컬렉션 뷰 셀, 컬렉션 뷰 셀에서 컬렉션 뷰, 컬렉션 뷰에서 뷰 컨트롤러로 타고 올라가야겠죠 ? 이러한 사이클을 방지해주겠다는 의미가 되는 것입니다.
지금까지의 내용을 한 마디로 정리하자면, 클로저에서 [weak self]와 [unowned self]를 붙여주는 이유는 retain cycle, 즉 메모리 누수를 막기 위해서다 ... 라고 할 수 있겠네요 ㅎㅎ
마무리 하겠습니다 ~!
혹시 잘못된 내용이 있다면 댓글로 꼭 알려주세요!
참고
- [Swift] weak, unowned, Retain cycle 톺아보기
- [Swift] ARC 뿌시기
- unowned self vs weak self (캡쳐 리스트)-(1)
'개발 > iOS' 카테고리의 다른 글
[iOS] UDID (Unique Device Identifier) (2) | 2022.03.16 |
---|---|
[iOS] UICollectionView (0) | 2022.03.12 |
[iOS] CollectionView의 extension으로 EmptyView 만들기 (0) | 2022.02.19 |
[iOS] loadView() 오류: Could not load NIB in bundle '~ (loaded)' with name '~ViewController' (0) | 2022.02.17 |
[iOS] UITableViewCell에 유동적인 행 높이 지정하기 (동적으로 높이 조정하기) (0) | 2022.02.12 |
댓글