strong (강한 참조)
- Swift에서 객체를 참조할 때 기본으로 강한참조를 한다.
- 누군가 강하게 참조하고 있는 한, 메모리에서 절대 해제되지 않습니다.
- 참조하는 인스턴스의 Reference Count 를 증가시킨다.
weak (약한 참조)
- 참조하는 인스턴스의 Reference Count 를 증가시키지 않는다.
- 참조하는 인스턴스가 메모리에서 할당 해제될 경우 nil 이 할당된다.
- self는 "옵셔널 타입"(self?)로 사용
(약한 참조는 언제든 메모리에서 사라질 수 있기때문 -> nil이 될 수 있기 때문)
unowned (무소유 참조)
- 참조하는 인스턴스의 Reference Count 를 증가시키지 않는다.
- 메모리에서 할당 해제 되어도 nil이 되지 않는다.
(참조하는 인스턴스가 메모리에서 할당 해제되어도 여전히 Heap 영역에 인스턴스가 있던 곳을 가리키고 있음) - 할당 해제되지 않은 인스턴스를 참조한다고 확신하는 경우에만 무소유 참조를 사용해야한다.
순환참조
- Swift는 ARC (Automatic Reference Counting) 라는 방식으로 메모리 관리를 하고 있어 자동으로 메모리를 할당하고 해제
- 참조 카운트(reference count)가 0이 되면, 인스턴스는 메모리에서 해제되어야 되는데 만약 A 객체가 B객체를 강하게 참조 하고 있고 B객체가 A객체를 강하게 참조하면 서로에 대한 참조가 해제되지 않기 때문에 둘다 메모리에서 해제되지 않아 순환참조 발생
예시코드
- MailHandler → UIAlertController → UIAlertAction → 클로저 → MailHandler ...
- 내가 만든 UIAlertController 안의 버튼(UIAlertAction)이 나를 참조
- MailHandler 인스턴스가 생성시 (rc + 1) & UIAlertAction 클로저안에 self (MailHandler)를 사용 (rc + 1)
-> mailHandler = nil 이 되어도 참조 카운트는 1이 남음 & deinit을 호출하지 않음 -> 메모리 누수 발생
class MailHandler: ObservableObject {
@Published var showDefaultMailView = false
private func showMailErrorAlert() {
...
}
func showMailOptions() {
let alertController = UIAlertController(
title: "메일 보내기",
message: "메일을 보낼 앱을 선택해주세요",
preferredStyle: .actionSheet
)
alertController.addAction(UIAlertAction(title: "Mail 앱", style: .default) { _ in
if MFMailComposeViewController.canSendMail() {
self.showDefaultMailView = true
} else {
self.showMailErrorAlert()
}
})
}
}
해결 방법
1. week 사용
- 클로저가 MailHandler를 강하게 잡지 않음
- 참조하는 인스턴스의 Reference Count 를 증가시키지 않음
- mailHandler를 nil로 하면 참조 카운트가 0이 되고 메모리 할당 해제
alertController.addAction(UIAlertAction(title: "Mail 앱", style: .default) { [weak self] _ in
if MFMailComposeViewController.canSendMail() {
self?.showDefaultMailView = true
} else {
self?.showMailErrorAlert()
}
})
2. unknown 사용
- MailHandler가 절대 메모리 해제되지 않는 상황 에서만 사용
alertController.addAction(UIAlertAction(title: "Mail 앱", style: .default) { [unowned self] _ in
if MFMailComposeViewController.canSendMail() {
self.showDefaultMailView = true
} else {
self.showMailErrorAlert()
}
})
'개발 > swift' 카테고리의 다른 글
[swift] @StateObject와 @ObservedObject (0) | 2025.04.18 |
---|---|
[swift] 상태관리도구 (EnvironmentObject, ObservableObject, state) (0) | 2025.04.11 |
[swift] Codable & Hashable & Identifiable (0) | 2025.04.04 |
[swift] swift 언어 정리 (4) - 프로토콜 & 익스텐션 (0) | 2025.03.16 |
[swift] swift 언어 정리 (3) - 클래스 & 구조체 & 열거형 (0) | 2025.03.15 |