Jaka jest różnica między słabym odniesieniem, a nienazwanym odniesieniem?

Swift ma:

  • Mocne Referencje
  • Słabe Referencje
  • Unowned References

Czym się różni od słabego odniesienie?

Kiedy można bezpiecznie używać nieautoryzowanego odniesienia?

Czy niepodpisane referencje są zagrożeniem bezpieczeństwa jak wiszące wskaźniki W C / C++?

Author: Ralfonso, 2014-06-03

6 answers

Zarówno weak, jak i unowned odwołania nie tworzą strong przytrzymaj obiekt, o którym mowa (a.k.a. nie zwiększają liczby zatrzymań, aby zapobiec dealokacji obiektu przez ARC).

Ale dlaczego dwa słowa kluczowe? Rozróżnienie to ma związek z tym, że typy Optional są wbudowane w język Swift. Krótka historia o nich: Opcjonalne typy zapewniają bezpieczeństwo pamięci (działa to pięknie z regułami konstruktora Swifta - które są surowe w celu świadczenia).

A weak Referencja pozwala na to, aby obiekt stał się nil (dzieje się to automatycznie, gdy obiekt jest dealokowany), dlatego Typ Twojej właściwości musi być opcjonalny - więc Ty, jako programista, jesteś zobowiązany do sprawdzenia go przed użyciem (w zasadzie kompilator zmusza cię, na ile to możliwe, do napisania bezpiecznego kodu).

Odniesienie unowned zakłada, że nigdy nie stanie się nil podczas swojego życia. Musi być ustawiona nieużywana Referencja podczas inicjalizacji-oznacza to, że Referencja zostanie zdefiniowana jako nieobowiązkowy typ, który można bezpiecznie używać bez sprawdzania. Jeśli w jakiś sposób obiekt, do którego odnosi się, jest dealokowany, aplikacja zawiesi się, gdy zostanie użyty nieupoważniony odnośnik.

Z Apple docs :

Użyj słabego odniesienia, gdy jest ono ważne, aby to odniesienie stało się nil w pewnym momencie swojego życia. Z drugiej strony, użyj unowned odniesienie, gdy wiesz, że Referencja nigdy nie będzie zerowa został ustawiony podczas inicjalizacji.

W dokumentach jest kilka przykładów, które omawiają zachowanie cykli i jak je łamać. Wszystkie te przykłady pochodzą z docs.

Przykład dla słowa kluczowego 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?
}

A teraz, dla niektórych ASCII art (powinieneś iść zobacz docs - mają ładne diagramy):

Person ===(strong)==> Apartment
Person <==(weak)===== Apartment

Przykład Person i Apartment pokazuje sytuację, w której dwie właściwości, obie z których mogą być zerowe, mają potencjał, aby spowodować silny cykl odniesienia. Ten scenariusz najlepiej rozwiązać ze słabym odniesieniem. Oba byty mogą istnieć bez ścisłej zależności od drugiego.

Przykład dla słowa kluczowego 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 }
}

W tym przykładzie, a Customer może lub nie może mieć CreditCard, Ale CreditCard zawsze będzie związane z Customer. Aby to reprezentować, Klasa Customer ma opcjonalną właściwość card, ale klasa CreditCard ma nie-opcjonalna (i nieoznakowana) customer własność.

Customer ===(strong)==> CreditCard
Customer <==(unowned)== CreditCard

Przykład Customer i CreditCard pokazuje sytuację, w której jedna właściwość, która może być zerowa, a inna właściwość, która nie może być zerowa, może spowodować silny cykl odniesienia. Ten scenariusz najlepiej rozwiązać za pomocą nieoznakowanego odniesienia.

Notka od Apple:

Słabe odniesienia muszą być zadeklarowane jako zmienne, aby wskazać, że ich wartość może się zmieniać w czasie wykonywania. Słabe odniesienie nie może być zadeklarowane jako stała.

Istnieje również trzeci scenariusz, w którym obie właściwości powinny zawsze mieć wartość, a żadna z nich nie powinna być zerowa po zakończeniu inicjalizacji.

Istnieją również klasyczne scenariusze cyklu zatrzymywania, których należy unikać podczas pracy z zamknięciami.

W tym celu zachęcam do odwiedzenia dokumentów Apple, lub przeczytaniaksiążki .
 297
Author: Ilea Cristian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-12 09:38:24

Q1. Czym różni się "Nieoznane odniesienie" od "słabego odniesienia"?

Słabe Odniesienie:

Słabe odniesienie to odniesienie, które nie trzyma się mocno instancja, do której się odnosi, a więc nie powstrzymuje ARC od pozbycia się przywołana instancja. Ponieważ słabe referencje mogą mieć "brak wartości", musisz zadeklarować każde słabe odniesienie jako mające Typ opcjonalny. (Apple Docs)

Niepodpisane Odniesienie:

Podobnie jak słabe odniesienia, nieautoryzowane odniesienia nie trzymają się mocno w przypadku, do którego się odnosi. W przeciwieństwie do słabego odniesienia, jednak zakłada się, że Referencja nieujawniona zawsze ma wartość. Z tego powodu, nieautoryzowane odniesienie jest zawsze definiowane jako typ nieobowiązkowy. (Apple Docs)

Kiedy używać każdego:

Użyj słabego odniesienia, gdy jest ono ważne, aby to odniesienie stało się nil w pewnym momencie swojego życia. Odwrotnie, użyj unowned odniesienie, gdy wiesz, że odniesienie nigdy nie będzie zerowe, gdy to został ustawiony podczas inicjalizacji. (Apple Docs)


Q2. Kiedy można bezpiecznie używać "nieoznakowanego odniesienia"?

Jak zacytowano powyżej, zakłada się, że niepodpisane odniesienie zawsze ma wartość. Powinieneś więc używać go tylko wtedy, gdy masz pewność, że odniesienie nigdy nie będzie zerowe. W poniższym przykładzie dokumenty Apple ilustrują przypadek użycia nieautoryzowanych odniesień.

Przypuśćmy mamy dwie klasy Customer i CreditCard. Klient może istnieć bez karty kredytowej, ale karta kredytowa nie będzie istnieć bez klienta, tzn. można założyć, że karta kredytowa zawsze będzie miała klienta. Powinny więc mieć następującą relację:

class Customer {
    var card: CreditCard?
}

class CreditCard {
    unowned let customer: Customer
}

Q3. Czy "unowned reference" odnosi się do ryzyka bezpieczeństwa, takiego jak" zwisające wskaźniki " w C/C++

Nie sądzę.

Ponieważ nieautoryzowane odniesienia są po prostu słabymi odniesieniami, które mają gwarancję, że mają wartość, nie powinno to stanowić zagrożenia bezpieczeństwa w żaden sposób. Jeśli jednak spróbujesz uzyskać dostęp do nieznanego odniesienia po tym, jak instancja, do której się odwołuje, zostanie usunięta, spowoduje to błąd środowiska uruchomieniowego, a aplikacja ulegnie awarii.

To jedyne ryzyko, jakie z tym widzę.

Link do dokumentów Apple

 23
Author: Myxtic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-07 14:49:31

Jeśli self może być zerowe w użyciu zamknięcia [słabe self] .

If self nigdy nie będzie zerowe w użyciu zamknięcia [unowned self] .

Jeśli podczas używania [unowned self] wtedy self jest prawdopodobnie zerowy w pewnym momencie zamknięcia i prawdopodobnie musisz zamiast tego użyć [weak self] .

Zobacz przykłady użycia strong, słaba , oraz unowned w zamknięcia:

Https://developer.apple.com/library/ios/documentation/swift/conceptual/swift_programming_language/AutomaticReferenceCounting.html

 22
Author: TenaciousJay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-27 23:37:33

Wyciągi z link

Kilka punktów końcowych

  • aby ustalić, czy w ogóle trzeba się martwić o silne, słabe lub unowned, zapytaj: "Czy mam do czynienia z typami odniesienia". Jeśli pracujesz w przypadku Structs lub Enums ARC nie zarządza pamięcią dla tych typów i nie musisz się nawet martwić o podanie słabych lub nieowocowanych dla te stałe lub zmienne.
  • silne odniesienia są dobre w hierarchicznych relacjach, gdzie rodzic odwołuje się do dziecka, ale nie odwrotnie. W rzeczywistości silne referencje są najbardziej odpowiednim rodzajem odniesienia przez większość czasu.
  • gdy dwie instancje są ze sobą opcjonalnie powiązane, upewnij się, że że jeden z tych przypadków ma słabe odniesienie do drugiego.
  • gdy dwie instancje są ze sobą powiązane w taki sposób, że jeden z instancje nie mogą istnieć bez drugiej, instancja z obowiązkowa zależność musi zawierać nieujawnione odniesienie do drugiego przykład.
 4
Author: carelesslyChoosy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-28 14:31:22

Z książki Jona Hoffmana " Mastering Swift 4.":

Różnica między słabym odniesieniem a nieujawnionym odniesieniem polega na tym, że instancja, do której odnosi się słabe odniesienie, może być zerowa, podczas gdy instancja, do której odnosi się nieujawnione odniesienie, nie może być zerowa. Oznacza to, że gdy używamy słabego odniesienia, właściwość musi być opcjonalną właściwością, ponieważ może być zerowa.

 0
Author: H S Progr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-01 14:52:29

Odniesienia nienazwane są rodzajem słabego odniesienia używanego w przypadku relacji o tym samym czasie życia między dwoma obiektami, gdy obiekt powinien być własnością tylko jednego innego obiektu. Jest to sposób na stworzenie niezmiennego powiązania między obiektem a jedną z jego właściwości.

W przykładzie podanym w pośrednim filmie swift WWDC, osoba jest właścicielem karty kredytowej, a karta kredytowa może mieć tylko jednego posiadacza. Na karcie kredytowej, osoba nie powinna być własnością opcjonalną, ponieważ nie chcesz mieć karty kredytowej unoszącej się tylko z jednym właścicielem. Możesz przerwać ten cykl, czyniąc własność posiadacza na kredyt słabym punktem odniesienia, ale wymaga to również uczynienia go opcjonalnym, a także zmiennym (w przeciwieństwie do stałej). Nieujawnione odniesienie w tym przypadku oznacza, że chociaż karta kredytowa nie ma udziałów w osobie, jej życie zależy od niej.

class Person {
    var card: CreditCard?
}

class CreditCard {

    unowned let holder: Person

    init (holder: Person) {
        self.holder = holder
    }
}
 -1
Author: JuJoDi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-06 19:35:29