Sobes.tech
Middle

Jaké typy odkazů existují ve Swiftu?

sobes.tech AI

Odpověď od AI

Ve Swiftu existují tři hlavní typy odkazů na instance tříd:

  1. Silný odkaz (Strong Reference):

    • Jedná se o výchozí typ odkazu.
    • Silný odkaz zvyšuje čítač odkazů objektu.
    • Objekt nebude uvolněn z paměti, dokud na něj existuje alespoň jeden silný odkaz.
    • Hlavní příčinou úniků paměti v případě cyklických silných odkazů (strong reference cycles).
    class Person {
        let name: String
        init(name: String) { self.name = name }
        deinit { print("\(name) je uvolněn") }
    }
    
    var reference1: Person? = Person(name: "John")
    // reference1 je nyní silný odkaz, čítač odkazů Person se zvyšuje
    
  2. Slabý odkaz (Weak Reference):

    • Je deklarován klíčovým slovem weak.
    • Slabý odkaz nezvyšuje čítač odkazů objektu.
    • Používá se k prevenci strong reference cycles.
    • Je vždy volitelný (Optional), protože odkazovaný objekt může být kdykoliv deinitializován. Při deinitializaci se slabý odkaz automaticky nastaví na nil.
    class Apartment {
        let unit: String
        weak var tenant: Person? // Slabý odkaz
        init(unit: String) { self.unit = unit }
        deinit { print("Byt \(unit) je uvolněn") }
    }
    
    var john: Person? = Person(name: "John")
    var unit4A: Apartment? = Apartment(unit: "4A")
    
    john?.apartment = unit4A // Pokud by Apartment měl silný odkaz na Person
    unit4A?.tenant = john   // Slabý odkaz
    
    // Po odstranění silných odkazů budou objekty deinitializovány
    john = nil
    unit4A = nil
    // Výstup: "John je uvolněn", "Byt 4A je uvolněn"
    // Pokud by tenant byl silný odkaz, došlo by ke vzniku úniku paměti (cyklus silných odkazů)
    
  3. Nezávislý odkaz (Unowned Reference):

    • Je deklarován klíčovým slovem unowned.
    • Stejně jako slabý odkaz, nezvyšuje čítač odkazů objektu.
    • Používá se také k prevenci strong reference cycles.
    • Na rozdíl od weak není volitelný (Optional) a předpokládá, že odkazovaný objekt bude existovat po celou dobu "životnosti" nezávislého odkazu.
    • Pokud je odkazovaný objekt deinitializován před tím, než se stane neplatným odkaz unowned, dojde k chybě za běhu (runtime error).
    • Je vhodný pro situace, kdy jeden objekt vždy existuje, dokud existuje jiný související objekt (například vztah "rodič-dítě", kde rodič vlastní dítě, ale dítě nevlastní rodiče silně).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) { self.name = name }
        deinit { print("\(name) je uvolněn") }
    }
    
    class CreditCard {
        let number: Int
        unowned let customer: Customer // Nezávislý odkaz
    
        init(number: Int, customer: Customer) {
            self.number = number
            self.customer = customer // Přiřazení nezávislého odkazu je bezpečné v init
        }
        deinit { print("Karta #\(number) je uvolněna") }
    }
    
    var john: Customer? = Customer(name: "John Doe")
    john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Vymazání silného odkazu na Customer
    john = nil
    // Výstup: "John Doe je uvolněn", "Karta #1234567890123456 je uvolněna"
    // Nezávislý odkaz na customer v CreditCard byl platný, dokud customer existoval.
    // Pokud by CreditCard žil déle než Customer a pokusili bychom se přistoupit k customer přes nezávislý odkaz, došlo by k chybě.
    

Hlavní rozdíl mezi weak a unowned:

  • weak: objekt může být nil. Použijte, když životní cyklus objektů není striktně propojen (jeden může existovat bez druhého).
  • unowned: objekt nemůže být nil po inicializaci. Použijte, když jste si jisti, že odkazovaný objekt bude existovat alespoň do doby, než existuje odkazující objekt.