Вопрос проверяет способность выявлять и устранять утечки памяти, возникающие при взаимных ссылках объектов.
Цикл сильных ссылок возникает, когда два или более объектов удерживают друг друга сильными ссылками, и счётчики не обнуляются. Такое «замыкание» блокирует освобождение памяти. Чтобы избежать, используют слабые (weak) или безвладельческие (unowned) ссылки для «обрыва» цикла.
Механизм цикла:
Объект A содержит свойство strong на B, и B содержит strong на A.
Даже если внешние ссылки обнуляются, внутренние удерживают объекты.
Пример цикла:
class A {
var b: B?
}
class B {
var a: A?
}
var objA: A? = A()
var objB: B? = B()
objA!.b = objB
objB!.a = objA
objA = nil // count A = 1 (у B)
objB = nil // count B = 1 (у A)
// Ни один deinit не вызоветсяРазрыв цикла:
Использовать weak для обратной ссылки:
class B {
weak var a: A?
}Или unowned при гарантированном существовании объекта:
class B {
unowned let a: A
init(a: A) { self.a = a }
}Когда применять:
weak — когда свойство может стать nil во время жизни.
unowned — когда жизненный цикл зависимого объекта не превышает владельца.
Вывод:
Циклы сильных ссылок приводят к утечкам памяти. Слабые и безвладельческие ссылки помогают разорвать цикл и позволить ARC освободить объекты.