Middle
Ce tipuri de legături există în Swift?
sobes.tech AI
Răspuns de la AI
În Swift există trei tipuri principale de referințe la instanțele de clasă:
-
Referință puternică (Strong Reference):
- Acesta este tipul implicit de referință.
- O referință puternică crește contorul de referințe al obiectului.
- Obiectul nu va fi eliberat din memorie atâta timp cât există cel puțin o referință puternică.
- Principalul motiv pentru scurgerile de memorie în cazul ciclurilor de referință puternice (
strong reference cycles).
class Person { let name: String init(name: String) { self.name = name } deinit { print("\(name) este fiind dezinitializat") } } var reference1: Person? = Person(name: "John") // reference1 este acum o referință puternică, contorul de referințe al lui Person crește -
Referință slabă (Weak Reference):
- Este declarată cu cuvântul cheie
weak. - O referință slabă nu crește contorul de referințe al obiectului.
- Este utilizată pentru a preveni
strong reference cycles. - Este întotdeauna opțională (
Optional), deoarece obiectul la care face referire poate fi dezinitializat în orice moment. La dezinitializare, referința slabă devine automatnil.
class Apartment { let unit: String weak var tenant: Person? // Referință slabă init(unit: String) { self.unit = unit } deinit { print("Apartament \(unit) este fiind dezinitializat") } } var john: Person? = Person(name: "John") var unit4A: Apartment? = Apartment(unit: "4A") john?.apartment = unit4A // Dacă Apartment avea o referință puternică către John unit4A?.tenant = john // Referință slabă // După ștergerea referințelor puternice, obiectele vor fi dezinitializate john = nil unit4A = nil // Rezultat: "John este fiind dezinitializat", "Apartament 4A este fiind dezinitializat" // Dacă tenant ar fi fost o referință puternică, s-ar fi produs o scurgere de memorie (cyclică puternică) - Este declarată cu cuvântul cheie
-
Referință neasignată (Unowned Reference):
- Este declarată cu cuvântul cheie
unowned. - La fel ca referința slabă, nu crește contorul de referințe al obiectului.
- Este utilizată pentru a preveni
strong reference cycles. - Spre deosebire de
weak, nu este opțională (Optional) și presupune că obiectul la care face referire va exista pe toată durata "vieții" referinței neasignate. - Dacă obiectul la care face referire
unownedeste dezinitializat înainte ca referințaunownedsă devină invalidă, va apărea o eroare de execuție (runtime error). - Se potrivește situațiilor în care un obiect există întotdeauna atâta timp cât un alt obiect asociat există, dar nu invers (de exemplu, o relație "părinte-copil", unde părintele deține copilul, dar copilul nu deține părintele în mod puternic).
class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } deinit { print("\(name) este fiind dezinitializat") } } class CreditCard { let number: Int unowned let customer: Customer // Referință neasignată init(number: Int, customer: Customer) { self.number = number self.customer = customer // Atribuirea referinței neasignate în init este sigură } deinit { print("Card #\(number) este fiind dezinitializat") } } var john: Customer? = Customer(name: "John Doe") john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // Ștergerea referinței puternice către Customer john = nil // Rezultat: "John Doe este fiind dezinitializat", "Card #1234567890123456 este fiind dezinitializat" // Referința neasignată către customer în CreditCard a fost validă atâta timp cât customer a existat. // Dacă CreditCard ar fi trăit mai mult decât Customer și am încerca să accesăm customer prin referința neasignată, s-ar produce o eroare. - Este declarată cu cuvântul cheie
Diferența cheie între weak și unowned:
weak: obiectul poate finil. Folosiți-l când durata de viață a obiectelor nu este strict legată (unul poate exista fără celălalt).unowned: obiectul nu poate finildupă inițializare. Folosiți-l când sunteți sigur că obiectul referit va exista cel puțin până când va exista obiectul care face referire.