Open yoogail105 opened 2 years ago
위의 승관이와 부석순의 예제로 돌아가 보자. 승관이와 부석순의 활동이 끝나고 휴식기임. nil을 할당.
??
이게 바로 문제 상황인데, 무엇이 문제인지 살펴보면
자동으로 nil 할당
→ 메모리에서 해제자동으로 nil 할당
되는 특성 → weak
은 무조건 옵셔널 타입의 변수weak
을 붙여준다.weak
으로 선언한다.
= 두 프로퍼티 중, 수명이 더 짧은 인스턴스를 가리키고있는 것을 weak
으로 선언한다.
⇒ 두 프로퍼티 중, 먼저 nil이 될 수 있는 것을 weak으로 선언한다. (이부분이 진짜 헷갈렸는데, 나는 이렇게 생각하는 것이 가장 쉬웠따..)승관이와 부석순의 예제에서는
bbu = nil
을 먼저 작성했기 때문에, Singer인스턴스의 수명이 더 짧다.
그러므로 group에 weak을 붙여준다.
요런 상황... Group의 member 변수가 nil이 될 수 있으니, weak으로 선언한다.
weak
이라서 RC가 증가하지 않았다는 데에 있다.처음부터 살펴보면,
승관이라는 이름을 가진, Singer bbu 인스턴스 생성
Singer RC + 1 ⇒ Signer RC = 1
부석순이라는 이름을 가진, Group booseoksoon 인스턴스 생성
Group RC + 1 ⇒ Group RC = 1
윗 부분은 강한 순환 참조의 첫 단계와 똑같음. 중요한 것은 지금이다.
이제 nil을 통해 해제해 보겠음.
Group RC -1
⇒ Grop RC = 1
nil
할당
이런..이런 느낌..
이렇게 하면, 안전하게 메모리를 해제할 수 있어, 불필요한 메모리 누수를 막을 수 있다.
❗️주목❗️
booseoksoon?.member = bbu
bbu = nil
booseoksoon?.member
bbu = nil
을 할당한 후에, booseoksoon?.member
으로 접근을 해도 오류가 나지 않는다.nil
할당 된다.weak var member: Singer?
옵셔널 변수이고, nil이 들어갈 수 있으니까Error
Group
이 먼저 해제되기 때문에, 나중에 nil값을 가질 확률이 있는 unowned var member: Singer
으로 unowned
을 선언해 준다.
❗️주의❗️
아까 weak에 nil을 만났던 것과 같은 상황을 만들어 보겠음.
var bbu: Singer? = .init(name: "승관")
var booseoksoon: Group? = .init(name: "부석순", member: bbu!)
bbu?.group = booseoksoon!
bbu = nil
booseoksoon?.member
더 오래 존재해야 하는(nil값이 될 위험이 없어야 하는) bbu에 nil을 할당
→ weak
과는 다르게, unwouned
에서는 메모리에서 내려간 주소를 참조하고 있는 member변수에 자동으로 nil
을 할당하지 않는다.
→ Singer가 메모리에서 해제된 뒤 참조를 하려고 하면, 존재하지 않는 주소값을 가지고 있기 때문에 compile error
객체가 다른 객체를 참조되거나 소유된 횟수
Reference count!
→ ARC
스위프트에서는 reference count(retain count)를 통해서 heap에 올라간 메모리를 자동으로 내려준다.
RC = 0이 되면 heap되면 메모리에서 해제시켜서 할당되었던 메모리를 다시 사용할 수 있게 해줌.
아무 키워드도 쓰지 않고 특정 객체를 참조하는 경우에는 힙에 올라가면서 RC를 1 증가 시킨다.
그리고 참조가 해제되면 RC를 1 다운시킨다.
weak, unowned를 통해서 참조하게 되면 RC를 증가시키지 않는다.
순환 참조의 오류
Strong 강한참조
default
순환참조
라는 문제가 발생할 수 있다!순환참조
*ARC의 단점: 순환참조 시 영구적으로 메모리가 해제되지 않을 수 있다.
예시를 통해 살펴보자.
Group
: Singer 타입의 member 변수를 가지고 있음Singer
: Group 타입의 group 변수를 가지고 있음그런데 여기에서
⇒ 이렇게 두 객체가 서로가 서로를 참조하게 된 상황이 바로 순환 참조이다!