← Назад к вопросам

Какой вид ссылок гарантирует существование объекта?

1.6 Junior🔥 201 комментариев
#Управление памятью#Язык Swift

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Типы ссылок и гарантии существования объекта

ARC (Automatic Reference Counting) в Swift

В Swift существуют разные типы ссылок, которые по-разному влияют на жизненный цикл объекта.

1. Strong Reference (强引用)

Увеличивает счётчик удержания (retain count).

class Person {
    var name: String
    deinit { print("Person deinitialized") }
}

var person: Person? = Person()  // Retain count = 1
print(person?.name)  // Object exists

person = nil  // Retain count = 0
// Output: "Person deinitialized"

Strong reference гарантирует: Объект существует, пока на него есть strong ссылка.

2. Weak Reference (弱引用)

Не увеличивает счётчик удержания.

class Parent {
    var child: Child?
}

class Child {
    weak var parent: Parent?  // Weak ссылка
}

var parent: Parent? = Parent()  // Retain count = 1
var child: Child? = Child()  // Retain count = 1

parent?.child = child
child?.parent = parent  // Не увеличивает retain count родителя

parent = nil  // Retain count родителя = 0
// Parent деаллоцируется, даже если child ещё на него ссылается
print(child?.parent)  // nil (because parent was deallocated)

Weak reference НЕ гарантирует: Объект может быть удалён в любой момент.

3. Unowned Reference (无主引用)

Не увеличивает счётчик, но предполагает, что объект всегда существует.

class CreditCard {
    var owner: Person?  // Strong: владеет
}

class Person {
    unowned let card: CreditCard  // Unowned: уверены, что card существует
    
    init(card: CreditCard) {
        self.card = card
    }
}

let person = Person(card: CreditCard())
print(person.card)  // Safe, потому что person владеет card

Unowned reference гарантирует: Объект существует, пока существует владелец.

Сравнение типов ссылок

ТипRetain CountГарантияКогда использовать
Strong+1Объект существуетParent → Child
Weak0Может быть nilDelegate pattern
Unowned0Всегда существуетClosure capture

Практические примеры

Strong Reference:

class Container {
    var items: [String] = []
    func addItem(_ item: String) {
        items.append(item)  // Strong ссылка, items существуют
    }
}

let container = Container()
container.addItem("Apple")
// items существуют, пока существует container

Weak Reference (Delegate):

protocol UserDelegate: AnyObject {
    func userDidUpdate()
}

class UserManager {
    weak var delegate: UserDelegate?  // Не владеем delegate
    
    func updateUser() {
        delegate?.userDidUpdate()  // delegate может быть nil
    }
}

Unowned Reference (Closure):

class User {
    let name: String
    var onUpdate: (() -> Void)?
    
    init(name: String) {
        self.name = name
        
        // self существует, пока существует User
        onUpdate = { [unowned self] in
            print("User \(self.name) updated")
        }
    }
}

Жизненный цикл объектов

1. Создание
   var person = Person()
   // Retain count = 1 (person ссылается)

2. Добавляем strong ссылку
   var friend = person
   // Retain count = 2 (person и friend)

3. Удаляем strong ссылку
   friend = nil
   // Retain count = 1 (только person)

4. Удаляем последнюю strong ссылку
   person = nil
   // Retain count = 0
   // deinit вызывается, объект удаляется

Когда объект гарантированно существует

✅ Во время выполнения strong ссылки на него ✅ Во время выполнения unowned ссылки (если владелец существует) ✅ В параметре функции (параметр = strong ссылка) ✅ В локальной переменной (пока в scope)

❌ Не гарантировано: weak ссылка ❌ Не гарантировано: после удаления всех strong ссылок

Отладка Retain Count

import Foundation

let person = Person()
print(CFGetRetainCount(person as CFTypeRef) - 1)  // -1 для CFTypeRef

Ключевые правила

✅ Strong для ownership (Parent → Child) ✅ Weak для optional relationships (Delegate) ✅ Unowned когда уверены в существовании ✅ [weak self] в closures во всех случаях ✅ [unowned self] только когда уверены ❌ Не смешивай strong в обе стороны (retain cycle)

Понимание типов ссылок критично для управления памятью и избегания утечек в iOS.