ARC
자동으로 메모를 관리해주는 방식이다.
(Automatic Reference Counting)
ARC는 더이상 필요하지 않은 클래스의 인스턴스를 메모리에서 해제하는 방식으로 동작한다.
원하는 방향으로 메모리 관리가 이루어지려면 명확한 힌트를 주어야 한다. 인스턴스가 언제 메모리에서 해제될지 예측할 수 있도록 ARC에 적용되는 몇가지 규칙이 있다.
인스턴스가 계속해서 메모리에 남아있어야하는 명분을 만들어 주는 것이 강한참조이다.
인스턴스는 참조 횟수가 0이되는 순간 메모리에서 해제되는데,
인스턴스를 다른 인스턴스의 프로퍼티나 변수, 상수 등에 할당할 때 강한참조를 사용하면 사용 횟수가 1 증가한다. 참조의 기본은 강한참조이다.
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: "KIM") //인스턴스 참조 횟수: 1 변수에 person 클래스를 참조함
reference2 = reference1 //인스턴스의 참조 횟수: 2
reference3 = reference1 //인스턴스의 참조 횟수: 3
reference3 = nil //인스턴스의 참조 횟수: 2
reference2 = nil //인스턴스의 참조 횟수: 1
reference1 = nil //인스턴스의 참조 횟수: 0
//nil을 사용하면 참조 횟수가 1씩 감소함
인스턴스가 서로가 서로를 강한참조를 할 때 강한참조 순환 문제가 발생한다.
class Person {
let nameL: String
init(name: String) {
self.name = name
}
var room: Room? //Room을 참조함
deinit {
print(" ...")
}
}
class Room {
let number: String
init(number: String) {
self.number = number
}
var host: Person? //Person을 참조함 , 사람이 없을수도 있기에 옵셔널로 정의
deinit{
print("...")
}
}
var Kim: Person? = Person(name: "Kim") //Person의 참조 횟수 = 1
var room:Room? = Room(number "505") //Room의 참조 횟수 = 1
room?.host = Kim // Person의 참조 횟수 = 2
Kim?.room = room //Room의 참조 횟수 = 2
Kim = nil //Person의 참조 횟수 = 1
room = nil //Room의 참조 횟수 = 1
위처럼 서로를 참조하고 인스턴스 참조를 잘 못해버리면 인스턴스를 참조할 방법이 사라진다. 그러면 인스턴스 참조 횟수 1을 남겨둔채로 메모리 누수가 발생한다.
강한참조와 달리 자신이 참조하는 인스턴스의 참조 횟수를 증가시키지 않는다. 강한 참조의 문제점을 해결할 수 있다. 프로퍼티나 변수선언 앞에 weak 키워드를 사용해주면 된다. 대신 nil이 할당될 수 있어야 하기 때문에 상수에서 쓰일 수 없다.
.
.
weak var host: Person?
.
.
room?.host = Kim //참조 횟수 증가되지 않음
미소유참조 또한 인스턴스의 참조 횟수를 증가시키지 않는다. 미소유참조는 자신이 참조하는 인스턴스가 항상 메모리에 존재할 것이라는 전제를 기반으로 동작한다. 그렇기에 미소유참조를 하는 변수나 프로퍼티는 옵셔널이나 변수가 아니어도 된다.
unowned 키워드를 참조타입의 변수나 프로퍼티의 정의 앞에 사용한다.
-신용카드는 반드시 사람이 있어야한다 (미소유참조)
. (class Person 정의)
.
.
class CreditCard {
unowned let owner: Person //반드시 소유자가 존재해야함
}
클래스를 참조하는 옵셔널을 미소유로 표시할 수 있다.
미소유 옵셔널 참조는 항상 유효한 객체를 가르키거나 그렇지 않으면 nil을 할당해주도록 직접 신경써야한다.
unowned var nextSubject: Subject? //옵셔널로 표시함
self.nextSubject = nil //nil이거나 next Subject가 유효한 객체를 가리켜야한다.
클로저의 참조순환 파트는 클로저 복습 후