애플 스위프트 공식 문서의 첫 문단
더보기
Swift uses Automatic Reference Counting (ARC) to track and manage your app’s memory usage. In most cases, this means that memory management “just works” in Swift, and you don’t need to think about memory management yourself. ARC automatically frees up the memory used by class instances when those instances are no longer needed.
스위프트는 당신의 앱 메모리 사용을 추적하고 관리하기 위해 자동 참조 세기(ARC)를 사용한다. 대부분의 경우, 이것은 스위프트가 메모리 관리를 "그냥 한다" 는 의미이고, 당신은 스스로 메모리 관리에 대해 생각할 필요가 없다. ARC는 해당하는 인스턴스가 더는 필요하지 않을 때 자동으로 사용하는 메모리를 해제한다.
RC
- Reference Counting
- 애플에서 메모리를 관리하는 방법
- 클래스의 인스턴스가 참조되면 카운트를 1씩 늘린다
ARC
- Automatic Reference Counting
- RC를 이용하여 자동으로 사용하지 않는 메모리는 해제해준다
- RC가 0이 되면 더 이상 참조되는 곳이 없다고 판단해서 메모리를 해제한다
Strong Reference
- 속성, 상수, 변수에 할당할 때의 기본 옵션
- strong 참조가 남아있는 동안은 할당 취소를 허용하지 않는다
- 각 인스턴스가 다른 인스턴스를 활성 상태로 참조하고 있을 때, 참조 순환이 발생한다
순환 참조 (+ 예시)
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
- 모든 사람이 부동산을 가진 것은 아니기 때문에 apartment는 선택사항(옵셔널)
- 모든 아파트 호실에 입주민이 있는 것은 아니므로 tenant는 선택사항(옵셔널)
var john: Person?
var unit4A: Apartment?
- Person 타입을 가지는 john 인스턴스를 생성
- Apartment 타입을 가지는 unit4A 인스턴스를 생성
john = Person(name: "John Appleseed")
unit4A = Apartment(unit: "4A")
- 각 인스턴스에 값을 할당해준다
- john과 unit4A는 각각 Person과 Apartment 클래스 인스턴스에 strong 참조를 한다. RC +1
john!.apartment = unit4A
unit4A!.tenant = john
- 각각 서로의 클래스 인스턴스를 타입으로 갖는 프로퍼티에 john과 unit4A를 할당한다. RC +1
- 해당 클래스 인스턴스 사이에 strong 참조 순환이 생겼다
- 각 클래스 인스턴스의 RC는 현재 2이다
john = nil
unit4A = nil
- 두 변수를 nil로 설정해도 메모리 해제 프로그램(deinit)이 실행되지 않는다
- 인스턴스 john과 unit4A의 메모리가 해제(RC -1)되어도, 클래스 인스턴스 사이의 참조 순환은 사라지지 않는다(클래스 인스턴스의 RC = 1) == 앱이 죽을때까지 메모리를 해제할 수 없다 (RC가 0이 아니기 때문에)
순환 참조 해결하기
- weak reference
- unowned references
- weak reference
- 클래스의 인스턴스를 참조해도 RC가 증가하지 않는다
- 메모리가 해제되면 nil을 할당한다
- 수명이 더 짧은 인스턴스에 선언한다
- weak reference 예시
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
weak var tenant: Person?
deinit { print("Apartment \(unit) is being deinitialized") }
}
- Apartment 클래스의 tenant를 weak reference로 선언
- Person 클래스 인스턴스는 weak로 선언되었기 때문에 RC가 늘어나지 않는다 = RC 1
- Apartment 클래스 인스턴스는 strong 으로 선언되었기 때문에 RC가 늘어난다 = RC 2
- john의 메모리를 해제하면, Person 클래스 인스턴스의 RC또한 0이 되므로 메모리가 해제
- 메모리가 해제된 클래스 인스턴스를 참조중이었던 Apartment 클래스 인스턴스의 프로퍼티인 tenant의 값에 nil이 할당 (RC = 1)
- 다시보는 weak reference의 특징 👉 메모리가 해제되면 nil을 할당한다
- unit4A의 메모리를 해제하면 Apartment 클래스 인스턴스의 RC값은 0이 되므로, 메모리가 해제된다
- unowned reference
- 클래스의 인스턴스를 참조해도 RC가 증가하지 않는다
- 옵셔널을 사용할 수 없다
- 항상 값을 가지고 있을 것으로 약속된 참조이므로, 할당 취소되지 않을 인스턴스에만 사용할 것
- 수명이 더 긴 인스턴스에 선언한다
클로저와 함께 사용? -> 추후 추가를...
Apple Swift Document https://docs.swift.org/swift-book/documentation/the-swift-programminglanguage/automaticreferencecounting/
'iOS > Swift' 카테고리의 다른 글
[Swift] 상속 Inheritance (0) | 2023.11.21 |
---|---|
[Swift] 프로퍼티 감시자 Property Observer (0) | 2023.11.21 |
[Swift] 연산 프로퍼티 Computed Property (1) | 2023.11.20 |
[Swift] 클래스/구조체 언제 사용할까? (0) | 2023.11.20 |
[Swift] 열거형 enum (0) | 2023.11.20 |