Middle
Jakie rodzaje referencji istnieją w Swift?
sobes.tech AI
Odpowiedź od AI
W Swift istnieją trzy główne typy odniesień:
-
**Silne odniesienie (Strong Reference):
- Zwiększa licznik odniesień do obiektu.
- Zapobiega deallokacji obiektu tak długo, jak istnieje co najmniej jedno silne odniesienie.
- Jest domyślnym typem odniesienia w Swift.
- Główną przyczyną cykli silnych odniesień.
-
**Słabe odniesienie (Weak Reference):
- Nie zwiększa licznika odniesień.
- Pozwala na deallokację obiektu, jeśli nie ma już silnych odniesień.
- Deklaruje się za pomocą słowa kluczowego
weak. - Zawsze jest opcjonalne (
Optional), ponieważ obiekt, na który się odwołuje, może stać sięnil. - Używa się go, aby zapobiec cyklom silnych odniesień, gdy jedna instancja może istnieć niezależnie od innej.
class Person { let name: String weak var apartment: Apartment? // Słabe odniesienie init(name: String) { self.name = name } deinit { print("\(name) deallokowany") } } class Apartment { let unit: String var tenant: Person? // Normalne silne odniesienie init(unit: String) { self.unit = unit } deinit { print("Mieszkanie \(unit) deallokowane") } } var john: Person? var unit4A: Apartment? john = Person(name: "John Appleseed") unit4A = Apartment(unit: "4A") john!.apartment = unit4A unit4A!.tenant = john // Tu mógłby powstać cykl silnych odniesień bez weak // Odwołania są zerowane, obiekty są deallokowane john = nil unit4A = nil -
**Odwołanie nieposiadane (Unowned Reference):
- Nie zwiększa licznika odniesień.
- Pozwala na deallokację obiektu, jeśli nie ma już silnych odniesień.
- Deklaruje się za pomocą słowa kluczowego
unowned. - Nie jest opcjonalne. Zakłada się, że obiekt, na który się odwołuje, zawsze będzie istnieć, dopóki istnieje instancja zawierająca to odwołanie.
- Użycie odwołania nieposiadanego na obiekcie, który już został deallokowany, spowoduje błąd w czasie wykonywania (crash).
- Używa się go, aby zapobiec cyklom silnych odniesień, gdy jedna instancja musi zawsze istnieć, dopóki istnieje inna, i nie ma możliwości, aby jeden z nich stał się
nilniezależnie od drugiego (np. w zamknięciachself).
class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } deinit { print("\(name) deallokowany") } } class CreditCard { let number: UInt64 unowned let customer: Customer // Odwołanie nieposiadane init(number: UInt64, customer: Customer) { self.number = number self.customer = customer } deinit { print("Karta #\(number) deallokowana") } } var john: Customer? = Customer(name: "John Appleseed") john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // Jeśli klient zostanie anulowany, karta odwołująca się do niego za pomocą unowned, // stanie się nieprawidłowa, ale nie spowoduje cyklu. john = nil // Oba obiekty są deallokowane
Wybór między weak a unowned zależy od charakteru relacji między obiektami: użyj weak, gdy jeden obiekt może istnieć bez drugiego (Person bez Apartment), i unowned, gdy jeden obiekt zawsze musi istnieć, dopóki istnieje drugi (CreditCard zawsze należy do Customer).