Sobes.tech
Middle

Kokie nuorodų tipai yra Swift?

sobes.tech AI

Atsakymas iš AI

Swift turi trys pagrindiniai nuorodų tipai į klasių pavyzdžius:

  1. Stipri nuoroda (Strong Reference):

    • Tai numatytasis nuorodų tipas.
    • Stipri nuoroda padidina objekto nuorodų skaitiklį.
    • Objektas nebus atlaisvintas iš atminties, kol turės bent vieną stiprią nuorodą.
    • Pagrindinė priežastis – ciklinės stiprios nuorodos (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 dabar stipri nuoroda, `Person` nuorodų skaitiklis didėja
    
  2. Silpna nuoroda (Weak Reference):

    • Deklaruojama naudojant žodį weak.
    • Silpna nuoroda nesudaro objekto nuorodų skaitiklio padidėjimo.
    • Naudojama siekiant išvengti strong reference cycles.
    • Visada yra pasirinktinė (Optional), nes nuoroda į objektą, į kurį nurodo silpna nuoroda, gali būti deinitializuota bet kuriuo metu. Deinitializacijos metu silpna nuoroda automatiškai tampa nil.
    class Apartment {
        let unit: String
        weak var tenant: Person? // Silpna nuoroda
        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 // Jei `Apartment` turėtų stiprią nuorodą į `Person`
    unit4A?.tenant = john   // Silpna nuoroda
    
    // Po stiprių nuorodų atšaukimo, objektai bus deinitializuoti
    john = nil
    unit4A = nil
    // Išvestis: "John is being deinitialized", "Apartment 4A is being deinitialized"
    // Jei `tenant` būtų stipri nuoroda, įvyktų atminties nutekėjimas (strong cycle)
    
  3. Nepageidaujama nuoroda (Unowned Reference):

    • Deklaruojama naudojant žodį unowned.
    • Panaši į silpną nuorodą, nes nesudaro objekto nuorodų skaitiklio padidėjimo.
    • Naudojama siekiant išvengti strong reference cycles.
    • Skirtingai nuo weak, nėra pasirinktinė (Optional) ir turi būti tikima, kad nuoroda į objektą egzistuos viso objekto gyvavimo ciklo metu.
    • Jei unowned nuoroda nurodo į objektą, kuris buvo deinitializuotas, įvyksta klaida vykdymo metu (runtime error).
    • Tinka situacijoms, kai vienas objektas visada egzistuoja, kol egzistuoja kitas susijęs objektas, bet ne atvirkščiai (pavyzdžiui, "tėvas-vaikas", kur tėvas valdo vaiką, bet vaikas nevaldo tėvo stipriai).
    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 // Nepageidaujama nuoroda
    
        init(number: Int, customer: Customer) {
            self.number = number
            self.customer = customer // Inicijavimo metu saugu
        }
        deinit { print("Card #\(number) is being deinitialized") }
    }
    
    var john: Customer? = Customer(name: "John Doe")
    john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Stiprios nuorodos į `Customer` išjungimas
    john = nil
    // Išvestis: "John Doe is being deinitialized", "Card #1234567890123456 is being deinitialized"
    // `CreditCard` viduje `customer` nuoroda buvo galiojanti, kol `customer` egzistavo.
    // Jei `CreditCard` gyventų ilgiau nei `Customer` ir bandytume pasiekti `customer` per `unowned` nuorodą, įvyktų klaida.
    

Pagrindinis skirtumas tarp weak ir unowned:

  • weak: objektas gali būti nil. Naudokite, kai objektų gyvavimo trukmė nėra griežtai susieta (vienas gali egzistuoti be kito).
  • unowned: objektas negali būti nil po inicializacijos. Naudokite, kai esate tikras, kad nuoroda į objektą egzistuos bent iki tol, kol egzistuos objektą nurodantis objektas.