Sobes.tech
Middle

Aké typy odkazov existujú v Swift?

sobes.tech AI

Odpoveď od AI

V jazyku Swift existujú tri hlavné typy odkazov:

  1. Silný odkaz (Strong Reference):

    • Zvyšuje čítač odkazov na inštanciu objektu.
    • Zabráni uvoľneniu objektu, kým existuje aspoň jeden silný odkaz naň.
    • Je predvolený typ odkazu v Swift.
    • Môže viesť ku kruhovým odkazom.
  2. Slabý odkaz (Weak Reference):

    • Nezvyšuje čítač odkazov.
    • Umožňuje uvoľnenie objektu, ak naň nie sú žiadne silné odkazy.
    • Je deklarovaný kľúčovým slovom weak.
    • Vždy je voliteľný (Optional), pretože odkazovaný objekt môže byť nil.
    • Používa sa na prevenciu kruhových odkazov.
    class Person {
        let name: String
        weak var apartment: Apartment? // Slabý odkaz
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) bol uvoľnený") }
    }
    
    class Apartment {
        let unit: String
        var tenant: Person? // Bežný silný odkaz
        init(unit: String) {
            self.unit = unit
        }
        deinit { print("Byt \(unit) bol uvoľnený") }
    }
    
    var john: Person?
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    
    john!.apartment = unit4A
    unit4A!.tenant = john // Tu by vznikol cyklický odkaz bez `weak`
    
    // Odkazy sa nulujú, objekty sa uvoľňujú
    john = nil
    unit4A = nil
    
  3. Unowned odkaz (Nepodporovaný odkaz):

    • Nezvyšuje čítač odkazov.
    • Umožňuje uvoľnenie objektu, ak naň nie sú žiadne silné odkazy.
    • Je deklarovaný kľúčovým slovom unowned.
    • Nie je voliteľný. Predpokladá sa, že odkazovaný objekt bude vždy existovať, kým existuje obsahujúca inštancia.
    • Prístup k uvoľnenému objektu cez unowned spôsobí runtime chybu (crash).
    • Používa sa na prevenciu kruhových odkazov, keď jeden objekt musí vždy existovať, kým existuje druhý, a nie je možné, aby jeden z nich bol nil.
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) bol uvoľnený") }
    }
    
    class CreditCard {
        let number: UInt64
        unowned let customer: Customer // Nepodporovaný odkaz
        init(number: UInt64, customer: Customer) {
            self.number = number
            self.customer = customer
        }
        deinit { print("Kreditná karta #\(number) bola uvoľnená") }
    }
    
    var john: Customer? = Customer(name: "John Appleseed")
    john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Ak zmažeme klienta, karta na neho odkazujúca pomocou `unowned` sa stane neplatná, ale nevytvorí cyklus.
    john = nil // Oba objekty sa uvoľnia
    

Voľba medzi weak a unowned závisí od charakteru vzťahu medzi objektmi: použite weak, keď jeden objekt môže existovať bez druhého (Person bez Apartment), a unowned, keď jeden objekt vždy musí existovať, kým existuje druhý (CreditCard vždy patrí Customer).