develop
ARC(Automatic Reference Counting) 본문
ARC(Automatic Reference Counting)
클래스의 인스턴스를 만들고 참조할 때 ARC가 인스턴스에 대한 정보를 메모리에 할당한다.
프로퍼티, 상수, 변수에 레퍼런스가 지정되면 카운트가 올라가고
해제되면 내려가고 0이되면 해제한다.
자동 레퍼런트 카운터는 더 이상 사용되지 않는 시점을 결정하여 메모리를 해제한다.
메모리가 제대로 해지되지 않는 경우가 있다.
순환참조
두 클래스 인스턴스의 프로퍼티가 서로를 강한 참조할 경우
class Example1 {
deinit {
print("deinit Example1")
}
var example2: Example2!
}
class Example2 {
deinit {
print("deinit Example2")
}
var examle1: Example1!
}
let example1 = Example1()
let example2 = Example2()
example1.example2 = example2
example2.examle1 = example1
클로져 내부에서 객체를 참조할 경우
class Example3 {
deinit {
print("deinit Example3")
}
var name = "name"
lazy var example: () -> Void = {
print(self.name)
}
}
let example3 = Example3()
example3.example()
둘다 deinit이 호출이 되지 않는다.
해결방법은
1. weak 약한참조
strong 강한참조를 하게 되면 대상 객체에 대한 소유권을 가지기 때문에 레퍼런스 카운트가 증가하는데
약한참조는 객체에 대한 소유권을 가지지 않고 객체를 참조하는 것이기 때문에
레퍼런스 카운트가 증가하지 않고 대상 객체의 레퍼런스 카운트가 0이 되는 순간
자동으로 nil이 되고 메모리에서 삭제된다.
옵셔널 변수에만 가능
두 클래스 인스턴스의 프로퍼티가 서로를 강한 참조할 경우
class Example1 {
deinit {
print("deinit Example1")
}
var example2: Example2!
}
class Example2 {
deinit {
print("deinit Example2")
}
weak var examle1: Example1!
}
클로져 내부에서 객체를 참조할 경우
class Example3 {
deinit {
print("deinit Example3")
}
var name = "name"
lazy var example: () -> Void = { [weak self] in
print(self?.name)
}
}
[weak self] in 이나 [unowned self] in 를 캡쳐리스트라고 한다. self를 캡쳐한다.
2. unowned 미소유 참조
언노운 변수는 반드시 옵셔널이 아니어야 한다.
레퍼런스 카운트를 증가시키지 않고 대상객체에 대한 참조가 가능하다.
하지만 객체가 메모리에 해제되었을때는 존재하지 않기 때문에 메모리에 참조하면 크래쉬가 나서 앱이 종료된다.
두 클래스 인스턴스의 프로퍼티가 서로를 강한 참조할 경우
class Example1 {
deinit {
print("deinit Example1")
}
var example2: Example2!
}
class Example2 {
deinit {
print("deinit Example2")
}
unowned var examle1: Example1
init(example1: Example1) {
self.examle1 = example1
}
}
let example1 = Example1()
let example2 = Example2(example1: example1)
example1.example2 = example2
클로져 내부에서 객체를 참조할 경우
class Example3 {
deinit {
print("deinit Example3")
}
var name = "name"
lazy var example: () -> Void = { [unowned self] in
print(self.name)
}
}
weak와 언노운은 레퍼런스 카운트를 증가시키지 않으며 대상객체에 대한 참조가 가능한 점은 동일하지만 객체가 해제된 경우에 다르다.
그리고 ARC는 run time에 계속 실행되는게 아니라 complie time에 실행된다
compile time에 코드 분석을 통해 적절한 위치에 retain, release 등의 코드를 삽입해 주고 삽입된 코드는 run time에 실행이 된다retain, release를 통해 referenceCount를 증감시키다가 count 가 0이 되면 deinit 을 통해 해제 시키고
referenceCount 는 동적 할당된 object를 표현하는 HeapObject struct에서 접근이 가능하다
'iOS' 카테고리의 다른 글
Convenience init (0) | 2021.01.07 |
---|---|
LifeCycle (0) | 2021.01.06 |
Escaping noescaping (0) | 2021.01.04 |
Enumeration (0) | 2021.01.03 |
Subscript Optional (0) | 2021.01.02 |