Sobes.tech
Middle

Aké typy odkazov existujú v Swift?

sobes.tech AI

Odpoveď od AI

V Swift existujú tri hlavné typy odkazov na inštancie tried:

  1. Silná referencia (Strong Reference):

    • Ide o predvolený typ odkazu.
    • Silná referencia zvyšuje počítadlo odkazov objektu.
    • Objekt nebude uvoľnený z pamäti, kým na neho existuje aspoň jedna silná referencia.
    • Hlavnou príčinou únikov pamäti sú cyklické silné odkazy (strong reference cycles).
    class Person {
        let name: String
        init(name: String) { self.name = name }
        deinit { print("\(name) is being deinitialized") }
    }
    
    var reference1: Person? = Person(name: "John")
    // reference1 je teraz silná referencia, počet odkazov na Person sa zvyšuje
    
  2. Slabá referencia (Weak Reference):

    • Deklaruje sa pomocou kľúčového slova weak.
    • Slabá referencia nezvyšuje počítadlo odkazov na objekt.
    • Používa sa na prevenciu strong reference cycles.
    • Vždy je voliteľná (Optional), pretože objekt, na ktorý odkazuje slabá referencia, môže byť de-inicializovaný kedykoľvek. Pri de-inicializácii sa slabá referencia automaticky stáva nil.
    class Apartment {
        let unit: String
        weak var tenant: Person? // Slabá referencia
        init(unit: String) { self.unit = unit }
        deinit { print("Apartment \(unit) is being deinitialized") }
    }
    
    var john: Person? = Person(name: "John")
    var unit4A: Apartment? = Apartment(unit: "4A")
    
    john?.apartment = unit4A // Ak by Apartment mal silnú referenciu na Person
    unit4A?.tenant = john   // Slabá referencia
    
    // Po zrušení silných odkazov budú objekty de-inicializované
    john = nil
    unit4A = nil
    // Výstup: "John is being deinitialized", "Apartment 4A is being deinitialized"
    // Ak by tenant bola silná referencia, došlo by k úniku pamäti (strong cycle)
    
  3. Bezstarostná referencia (Unowned Reference):

    • Deklaruje sa pomocou kľúčového slova unowned.
    • Podobne ako slabá referencia, nezvyšuje počítadlo odkazov na objekt.
    • Používa sa na prevenciu strong reference cycles.
    • Na rozdiel od weak, nie je voliteľná (Optional) a predpokladá, že objekt, na ktorý odkazuje, bude existovať počas celého "životného cyklu" bezstarostnej referencie.
    • Ak je objekt, na ktorý odkazuje unowned referencia, de-inicializovaný skôr, než sa stane neplatnou, nastane runtime chyba.
    • Hodí sa do situácií, keď jeden objekt vždy existuje, kým existuje iný s ním spojený, ale nie naopak (napríklad "rodič-dieťa", kde rodič vlastní dieťa, ale dieťa ne vlastní rodiča silno).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) { self.name = name }
        deinit { print("\(name) is being deinitialized") }
    }
    
    class CreditCard {
        let number: Int
        unowned let customer: Customer // Bezstarostná referencia
    
        init(number: Int, customer: Customer) {
            self.number = number
            self.customer = customer // Priradenie bezstarostnej referencie je bezpečné v init
        }
        deinit { print("Card #\(number) is being deinitialized") }
    }
    
    var john: Customer? = Customer(name: "John Doe")
    john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Zrušenie silnej referencie na Customer
    john = nil
    // Výstup: "John Doe is being deinitialized", "Card #1234567890123456 is being deinitialized"
    // Bezstarostná referencia na customer v CreditCard bola platná, kým customer existoval.
    // Ak by CreditCard žil dlhšie ako Customer a pokúsili by sme sa odkazovať na customer cez bezstarostnú referenciu, nastala by chyba.
    

Kľúčový rozdiel medzi weak a unowned:

  • weak: objekt môže byť nil. Používajte, keď životnosť objektov nie je striktne previazaná (jeden môže existovať bez druhého).
  • unowned: objekt nemôže byť nil po inicializácii. Používa sa, keď ste si istí, že odkazovaný objekt bude existovať aspoň dovtedy, kým existuje odkazujúci objekt.