약한참조 (weak)
약한참조 (weak) 는 강한참조와 달리 자신이 참조하는 인스턴스의 참조 횟수를 증가시키지 않는다.
참조 타입의 프로퍼티나 변수의 선언 앞에 weak 키워드를 써주면 그 프로퍼티나 변수는 자신이 참조하는 인스턴스를 약한참조한다.
약한참조를 사용한다면 자신이 참조하는 인스턴스가 메모리에서 해제될 수도 있다는 것을 예상해볼 수 있어야 한다.
자신이 참조 횟수를 증가시키지 않았기 때문에 그 인스턴스를 강한참조하던 프로퍼티나 변수에서 참조 횟수를 감소시켜 0으로 만들면, 자신이 참조하던 인스턴스가 메모리에서 해제되기 때문이다.
약한참조와 상수, 옵셔널
약한참조는 상수에서 쓰일 수 없다.
만약 자신이 참조하던 인스턴스가 메모리에서 해제된다면 nil이 할당될 수 있어야 하기 때문이다.
또한 nil이 할당될 수 있어야 하므로 약한참조는 항상 옵셔널이어야 한다.
즉, 옵셔널 변수만 약한참조를 할 수 있다.
강한참조 순환 문제를 약한참조로 해결
class Person {
let name: String
init(name: String) {
self.name = name
}
var room: Room?
deinit {
print("\(name) is being deinitialized")
}
}
class Room {
let num: String
init(num: String) {
self.num = num
}
weak var host: Person? // 약한참조 !!!!
deinit {
print("Room \(num) is being deinitialized")
}
}
var domisol: Person? = Person(name: "domisol") // Person 참조 횟수 1
var room: Room? = Room(num: "606") // Room 참조 횟수 1
room?.host = domisol // Person 참조 횟수 그대로 1 !!!!!
domisol?.room = room // Room 참조 횟수 2
domisol = nil // Person 참조 횟수 0, Room 참조 횟수 1 !!!!!!
// " domisol ~~ deinit "
print(room?.host) // "nil"
room = nil // Room 참조 횟수 0
// " room ~~ deinit "
Room 클래스의 host 프로퍼티가 약한참조를 하도록 weak 키워드를 추가해서 정의한 코드이다.
각 Person 과 Room 인스턴스는 domisol 과 room 변수에 할당할 때 참조 횟수가 1이 된다.
그러나 room 변수가 참조하는 인스턴스의 host 프로퍼티가 약한참조를 하므로, domisol 이 참조하는 인스턴스를 room 의 host 프로퍼티에 참조하도록 할 때, 참조 횟수는 증가하지 않는다.
또한 domisol 변수가 참조했던 인스턴스의 참조 횟수가 0이 되며 인스턴스에서 해제될 때, 이 인스턴스의 room 프로퍼티가 참조하는 room 인스턴스의 참조 횟수도 1 감소한다.
즉, 인스턴스가 메모리에서 해제될 때 자신의 프로퍼티가 강한참조를 하던 인스턴스의 참조 횟수를 1 감소시킨다는 것을 알 수 있다.
마지막으로 print(room?.host) 를 찍어보면 nil 이 출력된다.
host 프로퍼티는 약한참조를 하기 때문에 자신이 참조하는 인스턴스가 메모리에서 해제되면 자동적으로 nil 을 할당한다 !!
마지막으로 room 에 nil 을 할당하며 참조 횟수를 0으로 만들고, 메모리에서 해제되도록 한다.
이렇게 약한참조를 통해 강한참조 순환 문제를 해결할 수 있다.
참고 : 한빛미디어 swift 프로그래밍 2판
+
IBOutlet 기본값이 weak 이기도 하고,
강한참조를 하게 될 경우 메모리가 부족할 수도 있기 때문에 weak 을 사용하는 게 보편적이다.
다만, 복잡한 계층 구조를 가지고 있는 뷰에서라면, 중간에 메모리에서 해제될 수도 있으므로 strong을 사용하기도 한다.
'swift' 카테고리의 다른 글
[swift] 클래스(class) (0) | 2020.06.22 |
---|---|
[swift] 구조체 (struct) (0) | 2020.06.22 |
[swift] ARC | 강한참조 (Strong) (0) | 2020.06.11 |
[swift] ARC란? (0) | 2020.06.11 |
[swift] 데이터 타입 | Any, AnyObject (0) | 2020.06.08 |