Sobes.tech
Middle

Какви видове връзки съществуват в Swift?

sobes.tech AI

Отговор от AI

В Swift има три основни вида референции към екземпляри на класове:

  1. Силна референция (Strong Reference):

    • Това е подразбиращият се тип референция.
    • Силната референция увеличава брояча на референциите на обекта.
    • Обектът няма да бъде освободен от паметта, докато има поне една силна референция към него.
    • Основната причина за течове на памет при циклични силни референции (strong reference cycles).
    class Person {
        let name: String
        init(name: String) { self.name = name }
        deinit { print("\(name) се освобождава") }
    }
    
    var reference1: Person? = Person(name: "John")
    // reference1 сега е силна референция, броячът на референциите на Person се увеличава
    
  2. Слаба референция (Weak Reference):

    • Обявява се с ключовата дума weak.
    • Слабата референция не увеличава брояча на референциите на обекта.
    • Използва се за предотвратяване на strong reference cycles.
    • Винаги е опционална (Optional), защото обектът, към който сочи, може да бъде деинициализиран по всяко време. При деинициализация, слабата референция автоматично става nil.
    class Apartment {
        let unit: String
        weak var tenant: Person? // Слаба референция
        init(unit: String) { self.unit = unit }
        deinit { print("Апартамент \(unit) се освобождава") }
    }
    
    var john: Person? = Person(name: "John")
    var unit4A: Apartment? = Apartment(unit: "4A")
    
    john?.apartment = unit4A // Ако апартаментът имаше силна референция към John
    unit4A?.tenant = john   // Слаба референция
    
    // След изтриване на силните референции, обектите ще бъдат деинициализирани
    john = nil
    unit4A = nil
    // Изход: "John се освобождава", "Апартамент 4A се освобождава"
    // Ако tenant беше силна референция, щеше да се получи теч на памет (strong cycle)
    
  3. Несвързана референция (Unowned Reference):

    • Обявява се с ключовата дума unowned.
    • Подобно на слабата референция, не увеличава брояча на референциите.
    • Използва се също за предотвратяване на strong reference cycles.
    • За разлика от weak, не е опционална (Optional) и предполага, че обектът, към който сочи, ще съществува през цялото "животно" на референцията.
    • Ако обектът, към който сочи unowned референцията, бъде деинициализиран преди unowned референцията да стане невалидна, ще възникне грешка по време на изпълнение (runtime error).
    • Подходящ е за ситуации, когато един обект винаги съществува, докато съществува друг свързан обект (например, връзка "родител-дете", където родителят притежава детето, но детето не притежава родителя силно).
    class Customer {
        let name: String
        var card: CreditCard?
        init(name: String) { self.name = name }
        deinit { print("\(name) се освобождава") }
    }
    
    class CreditCard {
        let number: Int
        unowned let customer: Customer // Несвързана референция
    
        init(number: Int, customer: Customer) {
            self.number = number
            self.customer = customer // Назначаването на несвързана референция в init е безопасно
        }
        deinit { print("Карта #\(number) се освобождава") }
    }
    
    var john: Customer? = Customer(name: "John Doe")
    john?.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
    
    // Изтриване на силната референция към Customer
    john = nil
    // Изход: "John Doe се освобождава", "Карта #1234567890123456 се освобождава"
    // Несвързаната референция към customer в CreditCard беше валидна, докато customer съществуваше.
    // Ако CreditCard живееше по-дълго от Customer и се опитвахме да достъпим customer чрез несвързаната референция, щеше да възникне грешка.
    

Ключовата разлика между weak и unowned:

  • weak: обектът може да бъде nil. Използвайте, когато жизненият цикъл на обектите не е строго свързан (един може да съществува без другия).
  • unowned: обектът не може да бъде nil след инициализация. Използвайте, когато сте сигурни, че реферираният обект ще съществува поне докато съществува рефериращият обект.