Sobes.tech
Middle

Jaké typy odkazů existují ve Swiftu?

sobes.tech AI

Odpověď od AI

V Swiftu existují tři hlavní typy odkazů:

  1. Silný odkaz (Strong Reference):

    • Zvyšuje čítač odkazů na instanci objektu.
    • Zabraňuje uvolnění objektu, dokud existuje alespoň jeden silný odkaz na něj.
    • Je výchozím typem odkazu ve Swiftu.
    • Může způsobit cyklické odkazy.
  2. Slabý odkaz (Weak Reference):

    • Nezvyšuje čítač odkazů.
    • Umožňuje uvolnění objektu, pokud na něj již nejsou žádné silné odkazy.
    • Je deklarován klíčovým slovem weak.
    • Vždy je volitelný (Optional), protože odkazovaný objekt může být nil.
    • Používá se k prevenci cyklických odkazů.
    class Person {
        let name: String
        weak var apartment: Apartment? // Slabý odkaz
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) byl uvolněn") }
    }
    
    class Apartment {
        let unit: String
        var tenant: Person? // Obvyklý silný odkaz
        init(unit: String) {
            self.unit = unit
        }
        deinit { print("Byt \(unit) byl uvolněn") }
    }
    
    var john: Person?
    var unit4A: Apartment?
    
    john = Person(name: "John Appleseed")
    unit4A = Apartment(unit: "4A")
    
    john!.apartment = unit4A
    unit4A!.tenant = john // Tady by vznikl cyklický odkaz bez `weak`
    
    // Odkazy jsou nulovány, objekty jsou uvolněny
    john = nil
    unit4A = nil
    
  3. Unowned odkaz (Nepodílený odkaz):

    • Nezvyšuje čítač odkazů.
    • Umožňuje uvolnění objektu, pokud na něj již nejsou žádné silné odkazy.
    • Je deklarován klíčovým slovem unowned.
    • Není volitelný. Předpokládá se, že odkazovaný objekt bude vždy existovat, dokud existuje obsahující instance.
    • Přístup k uvolněnému objektu přes unowned způsobí runtime chybu (crash).
    • Používá se k prevenci cyklických odkazů, když jeden objekt musí vždy existovat, dokud existuje druhý, a není možné, aby jeden z nich byl nil (například vázání self v uzávěrech).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) {
            self.name = name
        }
        deinit { print("\(name) byl uvolněn") }
    }
    
    class CreditCard {
        let number: UInt64
        unowned let customer: Customer // Nepodílený odkaz
        init(number: UInt64, customer: Customer) {
            self.number = number
            self.customer = customer
        }
        deinit { print("Kreditní karta #\(number) byla uvolněna") }
    }
    
    var john: Customer? = Customer(name: "John Appleseed")
    john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Pokud klient zmizí, karta na něj odkazující přes `unowned` se stane neplatnou, ale nevytvoří cyklus.
    john = nil // Obě objekty jsou uvolněny
    

Volba mezi weak a unowned závisí na povaze vztahu mezi objekty: použijte weak, když jeden objekt může existovat bez druhého (Person bez Apartment), a unowned, když jeden objekt vždy musí existovat, dokud existuje druhý (CreditCard vždy patří Customer).