ARC (Automatic Reference Counting)
- ARC 는 메모리 관리 기법 중 하나로, 객체나 인스턴스가 참조되는 횟수를 추적하여 메모리에서 해제할 시점을 결정합니다.
- ARC의 작동방식 :
- 객체 생성: 객체가 생성되면 참조 횟수가 1 증가합니다.
- 객체 참조: 객체를 다른 변수나 상수에 할당하면 해당 객체의 참조 횟수가 1 증가합니다.
- 참조 해제: 객체의 참조가 없어지면 (참조하는 변수나 상수가 없가나 nil 이 할당되면) 참조 횟수가 1 감소합니다.
- Zeroing Weak Reference: 약한 참조 (Week Reference)는 객체의 참조 횟수를 증가시키지 않고 추적합니다. 객체가 해제되면 약한 참조는 자동으로 nil로 설정됩니다.
class Person {
let name: String
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
var reference1: Person?
var reference2: Person?
var reference3: Person?
reference1 = Person(name: "John Appleseed")
reference2 = reference1
reference3 = reference1
reference1 = nil
reference2 = nil
reference3 = nil
강한 참조 순환 (Strong Reference Cycle)
- 우리가 흔히 사용하는 참조는 디폴트로 강한 참조 (Strong Reference)를 사용한다. 이 강한 참조를 잘못 사용하면 메모리 누수 (Memory Leak)가 발생할 수 있다.
- 가장 대표적인 예시가 강한참조순환이다. 두 개 이상의 인스턴스가 서로를 참조해서 발행하는 문제다.
class Man {
var name : String
var girlFriend : Woman?
init(name:String){
self.name = name
}
deinit {print(" Man Deinit ")}
}
class Woman {
var name : String
var boyFriend : Man?
init(name:String){
self.name = name
}
deinit {print(" Woman Deinit ")}
}
var sam : Man? = Man(name: "Sam")
var julia : Woman? = Woman(name: "Julia")
sam?.girlFriend = julia
julia?.boyFriend = sam
sam = nil
julia = nil
강한 참조 순환 문제 해결 방법
약한 참조 (Weak Reference)
- 약한 참조 (Weak Reference): 참조되는 대상을 약하게 참조하여 순환참조를 방지한다.
weak
는 옵셔널로 선언되는 참조이다.
- 약한 참조는 참조하는 객체를 강제로 유지하지 않고, 참조 대상이 메모리에서 해제되면 자동으로 nil로 설정된다.
- 순한 참조를 방지하기 위해 사용되고 한쪽을 weak로 선언하여 순환 참조 문제를 해결할 수 있다. 근데 양쪽에 weak로 선언하는게 일반적이라고 한다.
class Man {
var name : String
weak var girlFriend : Woman?
init(name:String){
self.name = name
}
deinit {print(" Man Deinit ")}
}
class Woman {
var name : String
var boyFriend : Man?
init(name:String){
self.name = name
}
deinit {print(" Woman Deinit ")}
}
var sam : Man? = Man(name: "Sam")
var julia : Woman? = Woman(name: "Julia")
sam?.girlFriend = julia
julia?.boyFriend = sam
sam = nil
julia = nil
비소유 참조 ( Unowned Reference)
- 비소유 참조 ( Unowned Reference) : 참조되는 대상이 항상 유효한 경우에만 사용하며, 해당 대상이 해제될 수 있는 상황에는 사용하지 않는다.
unowned
는 옵셔널이 아닌 비소유 참조를 나타낸다.
- 비소유 참조는 항상 값이 있다고 가정하며, 참조하는 객체가 해제되면 런타임 에러가 발생할 수 있다.
class Man {
var name : String
unowned var girlFriend : Woman?
init(name:String){
self.name = name
}
deinit {print(" Man Deinit ")}
}
class Woman {
var name : String
unowned var boyFriend : Man?
init(name:String){
self.name = name
}
deinit {print(" Woman Deinit ")}
}
var sam : Man? = Man(name: "Sam")
var julia : Woman? = Woman(name: "Julia")
sam?.girlFriend = julia
julia?.boyFriend = sam
sam = nil
julia = nil
sam.girlfriend