
약한 참조
- 강한 참조와 달리 자신이 참조하는 인스턴스의 참조 횟수를 증가시키지 않음
- 참조 타입의 프로퍼티나 변수의 선언 앞에
weak 키워드를 사용하면 그 프로퍼티나 변수는 자신이 참조하는 인스턴스를 약한 참조함 - 약한 참조를 사용하면 자신이 참조하는 인스턴스가 메모리에서 해제될 수 도 있다는 것을 예상할 수 있음
- 참조하는 인스턴스에 대한 참조를 강하게 유지하지 않기 때문에 약한 참조로 참조되고 있는 동안에도 해당 인스턴스가 할당 해제될 수 있음
ARC는 인스턴스가 할당 해제될 때 해당 인스턴스를 약한 참조하는 프로퍼티를nil로 초기화함- 때문에 약한 참조는 항상 옵셔널 변수에만 사용 가능하며, 약한 참조는 상수에서 쓰일 수 없음
약한 참조와 상수, 옵셔널
만약 자신이 참조하던 인스턴스가 메모리 해제되면 nil이 할당될 수 있어야 하기 때문에 약한 참조는 상수에서 쓰일 수 없다. 그래서 약한 참조를 할 땐 자신의 값을 변경할 수 있는 변수로 선언해야 한다. 또, nil이 할당될 수 있어야 하므로 약한참조는 당연히 항상 옵셔널이여야 한다. 즉, 옵셔널 변수에만 약한참조를 할 수 있다.
강한 참조 순환에서 사용했던 코드
<hide/>
class Person {
let name: String
init(name: String) {
self.name = name
}
var room: Room?
deinit {
print("\(name) is being deinitialized!")
}
}
class Room {
let number: String
init(number: String) {
self.number = number
}
var host: Person?
deinit {
print("Room \(number) is being deinitialized!")
}
}
var seogun: Person? = Person(name: "서근") // Person 인스턴스의 참조 횟수 : 1
var myRoom: Room? = Room(number: "50") // Room 인스턴스의 참조 횟수 : 1
seogun?.room = myRoom // Room 인스턴스의 참조 횟수 : 2
myRoom?.host = seogun // Person 인스턴스의 참조 횟수 : 2
seogun?.room = nil // Room 인스턴스의 참조 횟수 : 1
myRoom?.host = nil // Person 인스턴스의 참조 횟수 : 1
seogun = nil // Person 인스턴스의 참조 횟수 : 0
// 서근 is being deinitialized!
myRoom = nil // Room 인스턴스의 참조 횟수 : 0
// Room 50 is being deinitialized!
강한 참조 순환에서 사용했던 Room 클래스에서 host 프로퍼티를 약한 참조로 바꿔보면 다음과 같다.
class Person {
let name: String
init(name: String) {
self.name = name
}
var room: Room?
deinit {
print("\(name) is being deinitialized!")
}
}
class Room {
let number: String
init(number: String) {
self.number = number
}
//var host: Person?
weak var host: Person?
deinit {
print("Room \(number) is being deinitialized!")
}
}
그리고 seogun과 myRoom의 관계는 이러했다.
var seogun: Person? = Person(name: "서근") // Person 인스턴스의 참조 횟수 : 1
var myRoom: Room? = Room(number: "50") // Room 인스턴스의 참조 횟수 : 1
seogun?.room = myRoom // Room 인스턴스의 참조 횟수 : 2
myRoom?.host = seogun // Person 인스턴스의 참조 횟수 : 1 (약한 참조니까!!!!)

Person 인스턴스는 Room 인스턴스에 대에 강한 참조를 여전히 유지하고 있는데 반해, Room인스턴스는 Person 인스턴스에 대해 약한 참조를 가지게 됐다.
이는 seogun 변수에 nil을 할당해 Person 인스턴스에 대한 강한 참조를 해제하게 된다면, Person 인스턴스는 더 이상 강한 참조를 갖지 않게 된다.
그러니까 Person과 Room 클래스는 둘 다 강한 참조이고, myRoom 변수가 Room 인스턴스에 강한 참조 했고, 이것을 Person 인스턴스에 약한 참조로 전달했으니(참조 횟수 증가 안 함) Person 인스턴스는 var seogun 변수를 제외한 모든 인스턴스가 약한 참조인 것!
여기서 유일한 강한 참조인 var seogun에 nil을 주면?

더 이상 Person 인스턴스에 대한 강한 참조가 존재하지 않으므로, Person 인스턴스가 할당 해제 되었고, Person 인스턴스에 대해 약한 참조를 가지고 있던 host 프로퍼티는 nil이 된다.
print(myRoom?.host) //옵셔널 Person
seogun = nil // Person 인스턴스 참조 횟수 : 0 , Room 인스턴스의 참조 횟수 : 1
//서근 is being deinitialized!
print(myRoom?.host) //nil
왜 host가 nil 이냐? Person이 존재 하지 않으니까!
weak var host: Person? //Person이 존재하지 않으니까 host도 nil
이렇게 Room 인스턴스에 대한 강한 참조는 myRoom 변수가 가지는 강한 참조만 남게 된다. 이 강한 참조 마저 해제해 버린다면? Room 인스턴스는 더 이상 강한 참조를 가지지 않게 되면서 디이니셜라이저를 호출한다.
myRoom = nil // Room 인스턴스의 참조 횟수 : 0
//Room 50 is being deinitialized!
전체적인 코드를 보면 이러하다.
class Person {
let name: String
init(name: String) {
self.name = name
}
var room: Room?
deinit {
print("\(name) is being deinitialized!")
}
}
class Room {
let number: String
init(number: String) {
self.number = number
}
weak var host: Person?
deinit {
print("Room \(number) is being deinitialized!")
}
}
var seogun: Person? = Person(name: "서근") // Person 인스턴스의 참조 횟수 : 1
var myRoom: Room? = Room(number: "50") // Room 인스턴스의 참조 횟수 : 1
seogun?.room = myRoom // Room 인스턴스의 참조 횟수 : 2
myRoom?.host = seogun // Person 인스턴스의 참조 횟수 : 1 (약한 참조니까!!!!)
print(myRoom?.host) //옵셔널 Person
seogun = nil // Person 인스턴스의 참조 횟수 : 0 , Room 인스턴스의 참조 횟수 : 1
//서근 is being deinitialized!
print(myRoom?.host) //nil
myRoom = nil // Room 인스턴스의 참조 횟수 : 0
//Room 50 is being deinitialized!
다음 게시글은 미소유 참조에 대해 알아보도록 하겠습니다.
읽어주셔서 감사합니다 🤟
'SWIFT > Grammar' 카테고리의 다른 글
| Swift 기초 문법 모음 (9) | 2022.02.24 |
|---|---|
| Swift : 고급문법[ARC 메모리 관리4 - 미소유 참조(unowned)] (0) | 2022.02.19 |
| Swift : 고급문법 [ARC 메모리 관리 2 - 강한 참조 순환 문제] (0) | 2022.02.12 |
| Swift : 고급문법 [ARC 메모리 관리 1 - 강한 참조] (0) | 2022.02.10 |
| Swift: 기초문법 [데이터 타입 - Int와 UInt (feat.카멜케이스)] (4) | 2022.02.09 |





