iOS Strong & Weak Reference (ARC)
목차
Strong Reference
Swift 기본 참조 타입. 참조하는 인스턴스의 소유권을 가짐.
- 참조 카운트를 1 증가
- 참조가 유지되는 동안 인스턴스는 메모리에서 해제되지 않음
- 순환 참조 발생 시 해제 불가능한 상황 발생
class Person {
var name: String
var pet: Pet? // 기본적으로 strong reference
init(name: String) {
self.name = name
}
deinit {
print("\(name) is being deinitialized")
}
}
class Pet {
var name: String
var owner: Person? // 기본적으로 strong reference
init(name: String) {
self.name = name
}
deinit {
print("\(name) is being deinitialized")
}
}
// 강한 참조 순환 발생
var person: Person? = Person(name: "Alice")
var pet: Pet? = Pet(name: "Bobby")
person?.pet = pet
pet?.owner = person
// 강한 참조로 인해 두 객체 모두 메모리에서 해제되지 않음
person = nil
pet = nil
//person과 pet 내부의 pet, owner가 참조를 가지고 있으므로 해제가 안됨
//만일 헤제를 하고 싶다면 아래의 순서대로 수동으로 끊어줘야함
// 강한 참조를 수동으로 해제
person?.pet = nil // person -> pet 연결 끊기
pet?.owner = nil // pet -> person 연결 끊기
// 이제 두 객체는 메모리에서 정상적으로 해제됨
person = nil
pet = nil
// 출력:
// Alice is being deinitialized
// Bobby is being deinitializedWeak Reference
weak키워드로 선언- 참조 카운트를 증가시키지 않음
- 항상 Optional 타입이어야 함 — 참조 대상이 해제되면 자동으로
nil - 주로 부모-자식 관계에서 자식이 부모를 약하게 참조할 때 사용
class Person {
var name: String
weak var pet: Pet? // 약한 참조
init(name: String) {
self.name = name
}
deinit {
print("\(name) is being deinitialized")
}
}
class Pet {
var name: String
var owner: Person? // 강한 참조
init(name: String) {
self.name = name
}
deinit {
print("\(name) is being deinitialized")
}
}
// 약한 참조로 강한 순환 참조 방지
var person: Person? = Person(name: "Alice")
var pet: Pet? = Pet(name: "Bobby")
person?.pet = pet // person이 pet을 약하게 참조
pet?.owner = person // pet이 person을 강하게 참조
// person과 pet 모두 메모리에서 정상적으로 해제됨
person = nil
pet = nil
// 출력:
// Alice is being deinitialized
// Bobby is being deinitialized비교
| 특징 | Strong | Weak |
|---|---|---|
| 참조 카운트 증가 | ✅ | ❌ |
| 객체 생명 주기 | 강하게 유지 | 대상 해제 시 자동 nil |
| 옵셔널 여부 | 불필요 | 항상 Optional |
| 사용 사례 | 일반적인 소유권 관계 | 순환 참조 방지, 비소유권 관계 |