You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
인스턴스를 생성하고 사용하던 것이 다 strong이자 강한 참조 - > default 값이 Strong
// strong (강한 참조)
classHuman{varname:String?varage:Int?init(name:String?, age:Int?){self.name = name
self.age = age
}}
//인스턴스의 주소값이 변수에 할당될 때, RC가 증가하면 강한 참조(strong)
letkim=Human(name:"kim", age:26)
클래스 인스턴스간 강한 참조 순환 (Strong Reference Cycles Between Class Instances)
클래스의 인스턴스간 강하게 상호 참조를 하고 있는 경우
classPerson{letname:Stringinit(name:String){self.name = name }varapartment:Apartment?deinit{print("\(name) is being deinitialized")}}classApartment{letunit:Stringinit(unit:String){self.unit = unit }vartenant:Person?deinit{print("Apartment \(unit) is being deinitialized")}}
//옵셔널 타입의 두 변수를 정의하는데 지정된 Apartment와 Person 인스턴스를 가지는데 nil로 우선 초기화
varjohn:Person?varunit4A:Apartment?
//각각 인스턴스를 만들어 변수에 할당
john =Person(name:"John Appleseed")
unit4A =Apartment(unit:"4A")
Person이라는 클래스는 변수로 Apartment 클래스의 인스턴스를 소유하고 있고 그 Apartment클래스에서는 변수로 Person형의 인스턴스를 소유
john 변수는 새로운 Person 인스턴스에 강한 참조를 가지며, unit4A 변수는 새로운 Apartment 인스턴스에 강력 참조를 가진다.
상수 또는 변수에 클래스 인스턴스를 할당 할 때, 해당 인스턴스에 대한 참조 → 기본적으로 강한 참조
Heap영역에서 서로가 서로를 참조
인스턴스 안의 apartment와 tenant가 각각 Apartment, Person 인스턴스를 참조하고 있는 상황 → Person 인스턴스의 참조 횟수 2, Apartment의 인스턴스 참조 횟수 2
john =nil
unit4A =nil
이 시점에서 nil을 할당해 참조를 해지 → 각각의 deinit이 호출되지 않음.
Heap 영역에서 서로를 강하게 참조하고 있기 때문이죠 → RC가 0이 아니기 때문
john과 unit4A는 각 인스턴스에 대한 참조를 하고 있지 않지만 Person 인스턴스와 Apartment 인스턴스의 변수가 각각 상호 참조를 하고 있어 참조 횟수가 1
저 강한 참조를 해제하고 싶어도 john과 unit4A이 nil이기 때문에 접근할 수 없음
메모리 누수가 발생
이런 상황을 ***강한 순환 참조(Strong Reference Cycles)***라고 함 → 영원히 메모리가 남음
weak (약한 참조)
약한 참조의 핵심
인스턴스를 참조할 시, RC를 증가시키지 않는다
참조하던 인스턴스가 메모리에서 해제된 경우, 자동으로 nil이 할당되어 메모리가 해제된다
프로퍼티를 선언한 이후, 나중에 nil이 할당 → weak는 무조건 옵셔널 타입의 변수여야함
강한 순환 참조는 서로가 서로를 강하게 참조하고 있던 것이 문제였으니 둘 중 한 쪽을 weak로 선언
classPerson{letname:Stringinit(name:String){self.name = name }varapartment:Apartment?deinit{print("\(name) is being deinitialized")}}classApartment{letunit:Stringinit(unit:String){self.unit = unit }
// 약한 참조 선언 방법
weak vartenant:Person?deinit{print("Apartment \(unit) is being deinitialized")}}
//옵셔널 타입의 두 변수를 정의하는데 지정된 Apartment와 Person 인스턴스를 가지는데 nil로 우선 초기화
varjohn:Person?varunit4A:Apartment?
//각각 인스턴스를 만들어 변수에 할당
john =Person(name:"John Appleseed")
unit4A =Apartment(unit:"4A")
//tenant를 weak로 선언해주고, unit4A의 tenant에 john을 넣으면 이제 참조가 시작
unit4A!.tenant = john
tenant를 weak로 선언해주고, unit4A의 tenant에 john을 넣으면 이제 참조가 시작
apartment가 아닌 tenant에 weak를 선언한 이유 → 애플 : 다른 인스턴스의 수명이 더 짧은 경우 즉, 다른 인스턴스를 먼저 할당 해제 할 수 있는 경우 약한 참조를 사용
그러나 weak(약한 참조)를 선언해줬기 때문에 이 시점에서 Person 인스턴스에 대한 참조 회수는 변수 john이 참조하고 있는 1회 뿐
john =nil
// Prints "John Appleseed is being deinitialized"
john을 nil로 선언 시 deinit의 print가 찍힌다.
john을 nil로 선언하는 순간 john이 참조하고 있는 RC 1이 끊어지면서 RC가 0이 됨
참조하는 인스턴스가 메모리에서 해제되면 / 자동으로 weak 참조를 nil로 설정
순환 참조이지만 weak로 선언되어 RC 값을 올리지 않는 것 → 약한 순환 참조
unowned (미소유 참조)
unowned과 weak는 강한 순환 참조를 해결 할 수 있음 (RC 값을 증가시키지 않음)
약한 참조와는 다르게 미소유 참조는 항상 값이 있음을 가정 (뒤로가면 이해됨..)
weak와 반대로 다른 인스턴스의 수명이 동일하거나 수명이 더 긴 경우 unowned(미소유) 참조를 사용
참조하는 인스턴스가 메모리에서 해제되어도 자동으로 nil로 만들어주지 않음.
unowned 참조는 weak 참조와 달리 항상 값을 가질 것으로 예상 → ARC는 이 unowned값을 nil로 설정 X
nil로 변경되지 않으므로 let으로 선언가능
참고) swift5.0부턴 unowned 프로퍼티가 이제 Optional타입을 지원한다고 함
내가 unowned로 참조하고 있는 인스턴스가 메모리에서 나보다 먼저 해제가 안되면 되는것에 사용
// 고객은 신용카드가 없을 수 있다.
// 하지만 신용카드가 고객이 없을 수 없다. 항상 신용카드는 고객과 연결
classCustomer{letname:Stringvarcard:CreditCard?init(name:String){self.name = name
}deinit{print("\(name) is being deinitialized")}}classCreditCard{letnumber:UInt64
unowned letcustomer:Customerinit(number:UInt64, customer:Customer){self.number = number
self.customer = customer
}deinit{print("Card #\(number) is being deinitialized")}}
Customer는 card 변수로 CreditCard인스턴스를 참조하고 있고 CreditCard는 customer로Custome
인스턴스를 참조
customer는 미소유 참조 unowned로 선언 → 이유는 고객과 신용카드를 비교해 봤을때 신용카드는 없더라도 사용자는 남아있을 것이기 때문 (신용카드가 고객이 없을 수 없기 때문에 신용카드보다 고객이 먼저 없어지는 경우는 없음)
사용자는 항상 존재 그래서 CreditCard에 customer를 unowned로 선언
varjohn:Customer?
john =Customer(name:"John Appleseed")
john!.card =CreditCard(number:1234_5678_9012_3456, customer: john!)
John이 Customer 인스턴스를 참조하고 있고 CreditCard 인스턴스도 Customer Instance를 참조하고 있지만 미소유(unowned) 참조를 하고 있기 때문에 Customer 인스턴스에 대한 참조 횟수는 1회
john =nil
// prints "John Appleseed is being deinitialized"
// prints "Card #1234567890123456 is being deinitialized"
john을 nil로 할당하는 순간 위 강한(strong) 참조가 없어지면서 RC가 0이 되면서 순환참조가 없어짐
강한(Strong) 참조
클래스 인스턴스간 강한 참조 순환 (Strong Reference Cycles Between Class Instances)
Person
이라는 클래스는 변수로Apartment
클래스의 인스턴스를 소유하고 있고 그Apartment
클래스에서는 변수로Person
형의 인스턴스를 소유weak (약한 참조)
unowned (미소유 참조)
CreditCard
인스턴스를 참조하고 있고 CreditCard는 customer로Custome
인스턴스를 참조
참고자료
The text was updated successfully, but these errors were encountered: