Sobes.tech
Middle

Welke soorten koppelingen zijn er in Swift?

sobes.tech AI

Antwoord van AI

In Swift zijn er drie hoofdtypen referenties naar klasse-instanties:

  1. Sterke referentie (Strong Reference):

    • Dit is het standaardtype referentie.
    • Een sterke referentie verhoogt de referentieteller van het object.
    • Het object wordt niet vrijgegeven uit het geheugen zolang er minstens één sterke referentie is.
    • De belangrijkste oorzaak van geheugenlekken bij cyclische sterke referenties (strong reference cycles).
    class Person {
        let name: String
        init(name: String) { self.name = name }
        deinit { print("\(name) wordt gedeinitialiseerd") }
    }
    
    var reference1: Person? = Person(name: "John")
    // reference1 is nu een sterke referentie, de teller van Person wordt verhoogd
    
  2. Zwakke referentie (Weak Reference):

    • Wordt gedeclareerd met het sleutelwoord weak.
    • Een zwakke referentie verhoogt de referentieteller van het object niet.
    • Wordt gebruikt om strong reference cycles te voorkomen.
    • Is altijd optioneel (Optional), omdat het object waarnaar wordt verwezen mogelijk op elk moment gedeinitialiseerd kan worden. Bij deinitialisatie wordt de zwakke referentie automatisch nil.
    class Apartment {
        let unit: String
        weak var tenant: Person? // Zwakke referentie
        init(unit: String) { self.unit = unit }
        deinit { print("Appartement \(unit) wordt gedeinitialiseerd") }
    }
    
    var john: Person? = Person(name: "John")
    var unit4A: Apartment? = Apartment(unit: "4A")
    
    john?.apartment = unit4A // Als Apartment een sterke referentie op John had
    unit4A?.tenant = john   // Zwakke referentie
    
    // Na het verwijderen van sterke referenties worden de objecten gedeinitialiseerd
    john = nil
    unit4A = nil
    // Output: "John wordt gedeinitialiseerd", "Appartement 4A wordt gedeinitialiseerd"
    // Als tenant een sterke referentie was, zou er een geheugenlek ontstaan (strong cycle)
    
  3. Onbezette referentie (Unowned Reference):

    • Wordt gedeclareerd met het sleutelwoord unowned.
    • Net als de zwakke referentie, verhoogt het de referentieteller niet.
    • Wordt ook gebruikt om strong reference cycles te voorkomen.
    • In tegenstelling tot weak, is het niet optioneel (Optional) en gaat ervan uit dat het object waarnaar wordt verwezen zal bestaan gedurende de hele "levensduur" van de onbezette referentie.
    • Als het object waarnaar wordt verwezen wordt gedeinitialiseerd voordat de unowned referentie ongeldig wordt, treedt er een runtime-fout op.
    • Geschikt voor situaties waarin één object altijd bestaat zolang een ander gerelateerd object bestaat, maar niet andersom (bijvoorbeeld een "ouder-kind" relatie, waarbij de ouder het kind bezit, maar het kind de ouder niet sterk bezit).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) { self.name = name }
        deinit { print("\(name) wordt gedeinitialiseerd") }
    }
    
    class CreditCard {
        let number: Int
        unowned let customer: Customer // Onbezette referentie
    
        init(number: Int, customer: Customer) {
            self.number = number
            self.customer = customer // Toewijzing van onbezette referentie in init is veilig
        }
        deinit { print("Kaart #\(number) wordt gedeinitialiseerd") }
    }
    
    var john: Customer? = Customer(name: "John Doe")
    john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Verwijderen van sterke referentie naar Customer
    john = nil
    // Output: "John Doe wordt gedeinitialiseerd", "Kaart #1234567890123456 wordt gedeinitialiseerd"
    // De onbezette referentie naar customer in CreditCard was geldig zolang customer bestond.
    // Als CreditCard langer had geleefd dan Customer en we probeerden te verwijzen naar customer via de onbezette referentie, zou er een fout optreden.
    

Belangrijk verschil tussen weak en unowned:

  • weak: het object kan nil zijn. Gebruik dit wanneer de levensduur van objecten niet strikt verbonden is (één kan zonder de ander bestaan).
  • unowned: het object kan niet nil zijn na initialisatie. Gebruik dit wanneer je zeker weet dat het verweesde object zal bestaan zolang het verwijzende object bestaat.