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) is being deinitialized") }
    }
    
    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("Apartment \(unit) is being deinitialized") }
    }
    
    var john: Person? = Person(name: "John")
    var unit4A: Apartment? = Apartment(unit: "4A")
    
    john?.apartment = unit4A // Якби Apartment мав сильне посилання на Person
    unit4A?.tenant = john   // Слабке посилання
    
    // Після скидання сильних посилань, об'єкти будуть деінціалізовані
    john = nil
    unit4A = nil
    // Вивід: "John is being deinitialized", "Apartment 4A is being deinitialized"
    // Якби tenant була сильним посиланням, сталася б витік пам'яті (strong cycle)
    
  3. Безтурботне посилання (Unowned Reference):

    • Оголошується за допомогою ключового слова unowned.
    • Подібно до слабкого посилання, не збільшує лічильник посилань на об'єкт.
    • Використовується для запобігання strong reference cycles.
    • На відміну від weak, не є опціональним (Optional) і передбачає, що об'єкт, на який вона вказує, буде існувати протягом усього "життєвого циклу" безтурботної посилання.
    • Якщо об'єкт, на який вказує unowned посилання, деінціалізується раніше, ніж стане недійсним, виникне помилка виконання (runtime error).
    • Підходить для ситуацій, коли один об'єкт завжди існує, поки існує інший пов'язаний з ним об'єкт, але не навпаки (наприклад, "батько-дитина", де батько володіє дитиною, але дитина не володіє батьком сильно).
    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 // Безтурботне посилання
    
        init(number: Int, customer: Customer) {
            self.number = number
            self.customer = customer // Присвоєння безтурботного посилання безпечно в 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!)
    
    // Скидання сильної посилання на Customer
    john = nil
    // Вивід: "John Doe is being deinitialized", "Card #1234567890123456 is being deinitialized"
    // Безтурботне посилання на customer у CreditCard було дійсним, поки customer існував.
    // Якщо б CreditCard жив довше за Customer і ми спробували звернутися до customer через безтурботне посилання, сталася б помилка.
    

Ключова різниця між weak і unowned:

  • weak: об'єкт може бути nil. Використовуйте, коли тривалість життя об'єктів не строго пов'язана (один може існувати без іншого).
  • unowned: об'єкт не може бути nil після ініціалізації. Використовуйте, коли ви впевнені, що на об'єкт посилається, він існуватиме щонайменше до того, як існуватиме посилаючий об'єкт.