class Dog {
var name: String
var weight: Double
init(name: String, weight: Double) {
self.name = name
self.weight = weight
}
deinit {
print("\(name) 메모리 해제")
}
}
var choco: Dog? = Dog(name: "초코", weight: 15.0) //retain(choco) RC: 1
var bori: Dog? = Dog(name: "보리", weight: 10.0) //retain(bori) RC: 1
choco = nil // RC: 0
//release(choco)
bori = nil // RC: 0
//release(bori)
자동(Automatic)으로 할 것인지의 차이
[ARC모델의 기반: 소유정책과 참조카운팅]
1.소유정책 - 인스턴스는 하나이상의 소유자가 있는 경우 메모리에 유지됨
(소유자가 없으면, 메모리에서 제거)
2.참조카운팅 - 인스턴스(나)를 가르키는 소유자수를 카운팅
var dog1: Dog?
var dog2: Dog?
var dog3: Dog?
dog1 = Dog(name: "댕댕이", weight: 7.0) // RC + 1 RC == 1
dog2 = dog1 // RC + 1 RC == 2
dog3 = dog1 // RC + 1 RC == 3
dog3?.name = "깜둥이"
dog2?.name
dog1?.name
dog3 = nil // RC - 1 RC == 2
dog2 = nil // RC - 1 RC == 1
dog1 = nil // RC - 1 RC == 0 // 메모리 해제
weak Reference(약한 참조) | Unowned Refeerence (비 소유 참조) | |
---|---|---|
방식 | weak 키워드 | unowned 키워드 |
예시 | weak var pet: Dog? (nil 자동할당) | unowned var pet: Dog? (swift 5 버전 이후 , 옵셔널로 선언하는것 가능해짐 그렇지만 , nil 자동 할당 하지 않음) |
공통점 | 가르키는 인스턴스의 Rc의 숫자를 올라가지 않게 함 ( 인스턴스 사이의 강한 참조를 제거 ) weak/unowned로 선언한 변수를 통해 인스턴스에 접근은 가능하지만 , 인스턴스를 유지 시키는 것은 불가능 | 가르키는 인스턴스의 Rc의 숫자를 올라가지 않게 함 ( 인스턴스 사이의 강한 참조를 제거 ) weak/unowned로 선언한 변수를 통해 인스턴스에 접근은 가능하지만 , 인스턴스를 유지 시키는 것은 불가능 |
차이점 | 소유자에 비해 , 보다 짧은 생명주기를 가진 인스턴스를 참조할때 주로 사용 (인스턴스가 nil 로 확인 가능 , nil인 경우 작업을 중단하는 것 가능) | 소유자보다 인스턴스의 생명주기가 더 길거나 같은 경우에 사용 (인스턴스 nil로 확인 불가능, 실제 인스턴스가 해제 되었다면 에어 발생) |
class Dog {
var name: String
weak var owner: Person? // weak 키워드 ==> 약한 참조
init(name: String) {
self.name = name
}
deinit {
print("\(name) 메모리 해제")
}
}
class Person {
var name: String
weak var pet: Dog? // weak 키워드 ==> 약한 참조
init(name: String) {
self.name = name
}
deinit {
print("\(name) 메모리 해제")
}
}
var bori: Dog? = Dog(name: "보리")
var gildong: Person? = Person(name: "홍길동")
// 강한 참조 사이클이 일어나지 않음
bori?.owner = gildong
gildong?.pet = bori
// 메모리 해제가 잘됨(사실 이 경우 한쪽만 weak으로 선언해도 상관없음)
bori = nil
gildong = nil
class Dog1 {
var name: String
unowned var owner: Person1? // Swift 5.3 이전버전에서는 비소유참조의 경우, 옵셔널 타입 선언이 안되었음
init(name: String) {
self.name = name
}
deinit {
print("\(name) 메모리 해제")
}
}
class Person1 {
var name: String
unowned var pet: Dog1?
init(name: String) {
self.name = name
}
deinit {
print("\(name) 메모리 해제")
}
}
var bori1: Dog1? = Dog1(name: "보리1")
var gildong1: Person1? = Person1(name: "홍길동1")
// 강한 참조 사이클이 일어나지 않음
bori1?.owner = gildong1
gildong1?.pet = bori1
// 메모리 해제가 잘됨(사실 이 경우 한쪽만 unowned로 선언해도 상관없음)
bori1 = nil
gildong1 = nil