약한 참조와 소유하지 않은 참조의 차이점은 무엇입니까?
Swift의 특징:
- 강력한 레퍼런스
- 취약한 레퍼런스
- 소유하지 않은 레퍼런스
소유하지 않은 참조와 약한 참조는 어떻게 다릅니까?
언제 무소유 레퍼런스를 사용하는 것이 안전합니까?
소유하지 않은 참조는 C/C++의 포인터 행잉과 같은 보안 리스크입니까?
다.weak
★★★★★★★★★★★★★★★★★」unowned
를 해도, 「이러다」가은 아닙니다.strong
참조된 객체에 홀드합니다(예를 들어 ARC가 참조된 객체의 할당을 해제하지 않도록 유지 카운트를 늘리지 않습니다).
데데왜 왜워 워? ???은 …라는 가 있다.라는 사실과 관련이 있다.Optional
유형은 Swift 언어로 기본 제공됩니다.요약하자면, 옵션 타입은 메모리 안전성을 제공합니다(이는 Swift의 컨스트럭터 규칙(이 장점을 제공하기 위해 엄격한 규칙)과 잘 어울립니다).
A weak
를 하면, 「」가 될 .nil
(이것은 참조된 객체가 할당 해제되었을 때 자동으로 발생합니다).따라서 속성 유형은 옵션이어야 합니다.따라서 프로그래머로서 사용자는 그것을 사용하기 전에 확인할 의무가 있습니다(컴파일러는 가능한 한 안전한 코드를 작성하도록 강제합니다).
안unowned
에서는 절대 하고 있습니다.nil
그 . 시 되지 않은 . 즉, 는 검사없이 할 수 됩니다.초기화 중에 소유되지 않은 참조를 설정해야 합니다. 즉, 참조는 검사 없이 안전하게 사용할 수 있는 비옵션 유형으로 정의됩니다.참조 중인 객체의 할당이 해제된 경우 소유되지 않은 참조를 사용할 때 앱이 충돌합니다.
해당 기준이 유효할 때마다 수명 중 어느 시점에서 0이 되는 약한 기준을 사용하십시오.반대로 초기화 중에 설정된 참조가 영(0)이 되지 않는다는 것을 알고 있는 경우에는 소유자가 없는 참조를 사용하십시오.
문서에는 유지 사이클과 그 해제 방법에 대해 설명하는 예가 몇 가지 있습니다.이러한 예는 모두 문서에서 추출한 것입니다.
의 예weak
★★★★★★★★★★★★★★★★★★:
class Person {
let name: String
init(name: String) { self.name = name }
var apartment: Apartment?
}
class Apartment {
let number: Int
init(number: Int) { self.number = number }
weak var tenant: Person?
}
ASCII 아트에서는 다음 문서를 참조해 주십시오.이 문서는 예쁜 도표가 붙어 있습니다.
Person ===(strong)==> Apartment
Person <==(weak)===== Apartment
Person
★★★★★★★★★★★★★★★★★」Apartment
예시는 둘 다 0이 될 수 있는2개의 속성이 강한 참조 사이클을 일으킬 가능성이 있는 상황을 나타내고 있습니다.이 시나리오는 약한 참조로 해결하는 것이 가장 좋습니다.두 엔티티 모두 다른 엔티티에 완전히 의존하지 않고 존재할 수 있습니다.
의 예unowned
★★★★★★★★★★★★★★★★★★:
class Customer {
let name: String
var card: CreditCard?
init(name: String) { self.name = name }
}
class CreditCard {
let number: UInt64
unowned let customer: Customer
init(number: UInt64, customer: Customer) { self.number = number; self.customer = customer }
}
예에서는, 「」가 되고 있습니다.Customer
도 있고 수도 CreditCard
,,CreditCard
에 항상 관련지어집니다.Customer
「 」는Customer
에는 옵션 클래스가 .card
속,는CreditCard
에는 비옵션 소유권 없음)이 있습니다.customer
★★★★★★★★★★★★★★★★★★.
Customer ===(strong)==> CreditCard
Customer <==(unowned)== CreditCard
Customer
★★★★★★★★★★★★★★★★★」CreditCard
예시는 0이 허가된 속성과 0이 될 수 없는 속성의 각각이 강한 참조 사이클을 일으킬 가능성이 있는 상황을 나타내고 있습니다.이 시나리오는 소유자가 없는 참조로 해결하는 것이 가장 좋습니다.
Apple 노트:
실행 시 값이 변경될 수 있음을 나타내려면 약한 참조를 변수로 선언해야 합니다.약한 참조는 상수로 선언할 수 없습니다.
또한 초기화가 완료된 후에는 두 속성 모두 항상 값을 가져야 하며 두 속성 모두 0이 되어서는 안 되는 세 번째 시나리오도 있습니다.
또한 폐쇄 작업을 수행할 때 피해야 하는 전형적인 유지 주기 시나리오도 있습니다.
그러기 위해서는 Apple docs를 방문하시거나 책을 읽어보시기 바랍니다.
Q1. '무소유 레퍼런스'와 '취약 레퍼런스'는 어떻게 다른가집니까?
취약한 참조:
약한 참조는 참조가 참조하는 인스턴스를 강하게 유지하지 않으므로 ARC가 참조된 인스턴스를 폐기하는 것을 막지 않습니다.약한 참조는 "값 없음"을 가질 수 있으므로 모든 약한 참조를 선택적 유형으로 선언해야 합니다.(Apple Docs)
소유자가 없는 레퍼런스:
약한 참조와 마찬가지로 소유권이 없는 참조는 참조하는 인스턴스를 강하게 유지하지 않습니다.그러나 약한 참조와 달리 소유하지 않은 참조는 항상 가치가 있는 것으로 가정한다.따라서 소유권이 없는 참조는 항상 비선택적 유형으로 정의된다.(Apple Docs)
각 사용 시기:
해당 기준이 유효할 때마다 수명 중 어느 시점에서 0이 되는 약한 기준을 사용하십시오.반대로 초기화 중에 설정된 참조가 영(0)이 되지 않는다는 것을 알고 있는 경우에는 소유자가 없는 참조를 사용하십시오.(Apple Docs)
Q2. "소유하지 않은 참조"를 사용하는 것이 안전한 때는 언제입니까?
위에서 언급한 바와 같이, 소유되지 않은 참조는 항상 가치가 있는 것으로 가정한다.따라서 참조가 0이 되지 않을 것으로 확신하는 경우에만 사용해야 합니다.Apple Docs는 다음 예에서 소유되지 않은 참조의 사용 사례를 보여 줍니다.
두 클래스가 해 보겠습니다.Customer
★★★★★★★★★★★★★★★★★」CreditCard
신용 카드 없이도 고객은 존재할 수 있지만, 신용 카드는 고객 없이는 존재할 수 없습니다. 즉, 신용 카드에는 항상 고객이 있다고 가정할 수 있습니다.따라서 다음과 같은 관계를 맺어야 합니다.
class Customer {
var card: CreditCard?
}
class CreditCard {
unowned let customer: Customer
}
Q3. "소유하지 않은 참조" 참조는 C/C++의 "당글링 포인터"와 같은 보안 리스크입니까?
난 그렇게 생각 안 해.
소유되지 않은 참조는 가치가 보장되는 취약한 참조이므로 보안 위험이 되지 않습니다.그러나 참조하는 인스턴스가 할당 해제된 후 소유되지 않은 참조에 액세스하려고 하면 런타임 오류가 트리거되고 앱이 충돌합니다.
그게 내가 볼 수 있는 유일한 위험이야.
폐쇄에서 자아가 영(0)이 될 수 있다면 [약한 자아를 사용한다.
결말이 나지 않으면 [무소유자]를 이용하라.
만약 당신이 [소유하지 않은 자아]를 사용했을 때 그것이 무너진다면, 아마도 그 폐쇄의 어느 시점에서는 자아는 영(0)이 될 것이고, 당신은 그 대신 [약한 자아]를 사용해야 할 것이다.
클로저에 강한 것, 약한 것, 소유하지 않는 것의 사용 예를 참조해 주세요.
링크에서 추출합니다.
몇 가지 결론점
- 강한 것, 약한 것, 소유자가 없는 것에 대해 걱정할 필요가 있는지 판단하려면 "참조 유형을 취급하고 있습니까?"라고 질문합니다.Structures 또는 Enums를 사용하는 경우 ARC는 이러한 유형의 메모리를 관리하지 않으며, 이러한 상수 또는 변수에 대해 약한 메모리나 소유하지 않은 메모리를 지정할 필요도 없습니다.
- 부모가 자식을 참조하는 계층적 관계에서는 강한 참조가 좋습니다만, 그 반대는 아닙니다.사실, 강한 언급은 대부분의 경우 가장 적절한 종류의 언급이다.
- 두 인스턴스가 선택적으로 서로 관련되어 있는 경우 두 인스턴스 중 하나가 다른 인스턴스에 대한 참조가 약한지 확인하십시오.
- 인스턴스 중 하나가 다른 인스턴스 없이 존재할 수 없는 방식으로 두 인스턴스가 관련되어 있는 경우 필수 종속성을 가진 인스턴스는 다른 인스턴스에 대한 소유권이 없는 참조를 보유해야 합니다.
다.weak
★★★★★★★★★★★★★★★★★」unowned
참조는 객체의 참조 수에 영향을 주지 않습니다., 약한 즉,이 될 수 . 반면, 0은 0이 될 수 .unowned
참조는 0이 될 수 없기 때문에 선택사항이 될 수 없습니다.옵션 참조를 사용할 경우 오브젝트가 0일 가능성을 항상 처리해야 합니다.소유자가 없는 참조의 경우 오브젝트가 0이 되지 않도록 해야 합니다.영점 객체에 대한 소유권이 없는 참조를 사용하는 것은 영점 객체가 아닌 옵션의 강제 포장을 해제하는 것과 유사합니다.
즉, 개체의 수명이 참조 수명보다 길다고 확신하는 경우 소유되지 않은 참조를 사용하는 것이 안전하다고 합니다.그렇지 않은 경우 대신 약한 참조를 사용하는 것이 좋습니다.
질문의 세 번째 부분에 대해서는, 소유자가 없는 참조는, 달랑거리는 포인터와 비슷하지 않다고 생각합니다.기준 카운트에 대해 이야기할 때 일반적으로 객체의 강한 기준 카운트를 말합니다.마찬가지로 swift는 객체에 대한 소유자가 없는 참조 수와 약한 참조 수를 유지합니다(객체 자체가 아닌 "사이드 테이블"이라고 불리는 것에 대한 약한 참조 지점).강력한 참조 수가 0에 도달하면 개체는 초기화가 취소되지만 소유되지 않은 참조 수가 0보다 크면 할당을 취소할 수 없습니다.
매달림 포인터는 이미 할당 해제된 메모리 위치를 가리키는 것입니다.그러나 메모리는 오브젝트에 대한 소유권이 없는 참조가 있는 한 할당 해제될 수 있기 때문에 포인터가 흔들릴 수 없습니다.
신속한 메모리 관리에 대해 자세히 설명하는 기사가 많이 있습니다.여기 있습니다.
소유되지 않은 참조는 두 개체 간에 동일한 수명 관계가 있는 경우에 사용되는 약한 참조의 일종으로, 개체는 다른 개체에만 소유되어야 합니다.오브젝트와 그 속성 사이에 불변의 바인딩을 만드는 방법입니다.
중간 스위프트 WWDC 비디오의 예에서는 신용카드를 소유하고 있으며 신용카드를 소지할 수 있는 사람은 1명뿐입니다.신용 카드에서는, 한 명의 소유자와만 신용 카드가 떠돌고 싶지 않기 때문에, 그 사람은 선택적인 자산이 되어서는 안 된다.신용의 보유자 속성을 약한 참조로 만들면 이 사이클을 끊을 수 있지만, 이를 위해서는 (상수가 아닌) 옵션 및 가변으로 만들어야 합니다.이 경우 소유권이 없는 언급은 신용 카드가 개인에 대한 소유 지분을 가지고 있지 않지만 신용 카드의 존속 여부는 신용 카드에 달려 있음을 의미합니다.
class Person {
var card: CreditCard?
}
class CreditCard {
unowned let holder: Person
init (holder: Person) {
self.holder = holder
}
}
unowned
self
있을 수 없다nil
하고 있는 self
그 시점에서.
을 직접 할 수 .MyViewController
(예:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let myButton = MyButton { [unowned self] in
print("At this point, self can NEVER be nil. You are safe to use unowned.")
print("This is because myButton can not be referenced without/outside this instance (myViewController)")
}
}
}
class MyButton: UIButton {
var clicked: (() -> ())
init(clicked: (() -> ())) {
self.clicked = clicked
// We use constraints to layout the view. We don't explicitly set the frame.
super.init(frame: .zero)
addTarget(self, action: #selector(clicked), for: .touchUpInside)
}
@objc private func sendClosure() {
clicked()
}
}
weak
이 있을 때self
수 있습니다.nil
하고 있는 self
.
예:
class MyViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
NetworkManager.sharedInstance.receivedData = { [weak self] (data) in
print("Can you guarentee that self is always available when the network manager received data?")
print("Nope, you can't. Network manager will be alive, regardless of this particular instance of MyViewController")
print("You should use weak self here, since you are not sure if this instance is still alive for every")
print("future callback of network manager")
}
}
}
class NetworkManager {
static let sharedInstance = NetworkManager()
var receivedData: ((Data) -> ())?
private func process(_ data: Data) {
// process the data...
// ... eventually notify a possible listener.
receivedData?(data)
}
}
점의 unowned
:
- 약점보다 효율이 높다
- 인스턴스를 (Swift 5.0 이후로는) 불변으로 마크할 수 있습니다.
- 코드 판독기에 다음을 나타냅니다.이 인스턴스는 X와 관계가 있어 X가 없으면 살 수 없지만 X가 없어지면 나도 없어진다.
점의 weak
:
- 소유자가 없는 것보다 안전합니다(충돌하지 않기 때문에).
- X와의 관계를 쌍방향으로 만들 수 있지만 둘 다 서로 없이 살 수 있다.
확실하지 않은 경우 다음을 사용하십시오.weak
잠깐만요, StackOverflow에서 이 경우 어떻게 해야 하는지 물어보세요!항상 약하게 사용해서는 안 될 때 사용하는 것은 당신과 당신의 코드를 읽는 사람에게 혼란스러울 뿐입니다.
언급URL : https://stackoverflow.com/questions/24011575/what-is-the-difference-between-a-weak-reference-and-an-unowned-reference
'itsource' 카테고리의 다른 글
패널 또는 플레이스홀더 사용 (0) | 2023.04.22 |
---|---|
"sh" 또는 "bash" 명령을 사용하지 않고 셸 스크립트를 실행하려면 어떻게 해야 합니까? (0) | 2023.04.22 |
Azure 함수 - 함수는 정적 클래스 안에 작성해야 합니다. (0) | 2023.04.22 |
Swift 사전을 통한 반복 (0) | 2023.04.22 |
Django에서 여러 쿼리 세트를 결합하는 방법은 무엇입니까? (0) | 2023.04.22 |