Sobes.tech
Middle

Ce tipuri de referințe există în Swift?

sobes.tech AI

Răspuns de la AI

În Swift, există trei tipuri principale de referințe:

  1. **Referință Puternică (Strong Reference):

    • Crește contorul de referințe al obiectului.
    • Previene deallocarea obiectului atât timp cât există cel puțin o referință puternică.
    • Este tipul implicit de referință în Swift.
    • Cauza principală a ciclurilor de referințe puternice.
  2. **Referință Slabă (Weak Reference):

    • Nu crește contorul de referințe.
    • Permite deallocarea obiectului dacă nu mai există referințe puternice.
    • Se declară folosind cuvântul cheie weak.
    • Este întotdeauna opțională (Optional), deoarece obiectul referențiat poate deveni nil.
    • Se folosește pentru a preveni ciclurile de referințe puternice, atunci când o instanță poate exista independent de alta.
    class Person {
        let name: String
        weak var apartment: Apartment? // Referință slabă
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) deallocat") }
    }
    
    class Apartment {
        let unit: String
        var tenant: Person? // Referință puternică normală
        init(unit: String) {
            self.unit = unit
        }
        deinit { print("Apartament \(unit) deallocat") }
    }
    
    var john: Person?
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    
    john!.apartment = unit4A
    unit4A!.tenant = john // Aici s-ar putea crea un ciclu de referințe puternice fără weak
    
    // Referințele sunt resetate, obiectele sunt deallocat
    john = nil
    unit4A = nil
    
  3. **Referință Neasumată (Unowned Reference):

    • Nu crește contorul de referințe.
    • Permite deallocarea obiectului dacă nu mai există referințe puternice.
    • Se declară folosind cuvântul cheie unowned.
    • Nu este opțională. Se presupune că obiectul referențiat va exista întotdeauna atâta timp cât instanța care conține referința neasumată există.
    • Utilizarea unei referințe neasumate pe un obiect deja deallocat va duce la o eroare de execuție (crash).
    • Se folosește pentru a preveni ciclurile de referințe puternice, atunci când o instanță trebuie să existe întotdeauna atâta timp cât alta există, și nu există posibilitatea ca unul dintre ele să devină nil independent de celălalt (de exemplu, în închiderile self).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) deallocat") }
    }
    
    class CreditCard {
        let number: UInt64
        unowned let customer: Customer // Referință neasumată
        init(number: UInt64, customer: Customer) {
            self.number = number
            self.customer = customer
        }
        deinit { print("Card #\(number) deallocat") }
    }
    
    var john: Customer? = Customer(name: "John Appleseed")
    john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Dacă clientul este anulat, cardul care face referire la el cu unowned,
    // va deveni invalid, dar nu va cauza ciclu.
    john = nil // Ambele obiecte sunt deallocat
    

Alegerea între weak și unowned depinde de natura relației dintre obiecte: folosiți weak când un obiect poate exista fără celălalt (Person fără Apartment), și unowned când un obiect trebuie să existe întotdeauna atâta timp cât celălalt există (CreditCard aparține întotdeauna Customer).