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++?
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 .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ę.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:
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.
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.
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
}
}
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