Вопрос проверяет знание способов хранения слабых ссылок в коллекциях, которые по умолчанию хранят элементы сильно.
Обычный Swift-массив (Array) хранит сильные ссылки на объекты. Чтобы хранить weak-ссылки, можно использовать два основных подхода:
Обертка (Wrapper): Создать структуру или класс-обертку, которая содержит weak-ссылку, и хранить эти обертки в массиве.
NSPointerArray: Использовать класс из Foundation NSPointerArray, сконфигурированный для хранения weak-ссылок с помощью .weakMemory option.
Прямое добавление объекта в массив создает на него сильную ссылку, что может помешать освобождению памяти.
Способ 1: Обертка (Weak Reference Wrapper)
Создаем универсальную обертку, которая будет хранить weak-ссылку на любой объект.
class Weak<T: AnyObject> {
weak var value: T?
init(_ value: T) {
self.value = value
}
}
// Использование: храним массив оберток
var weakControllers: [Weak<UIViewController>] = []
let vc = UIViewController()
// Добавляем обертку со слабой ссылкой на vc
weakControllers.append(Weak(vc))
// Чтобы получить массив не-nil объектов, можно использовать compactMap
let activeControllers = weakControllers.compactMap { $0.value }Способ 2: NSPointerArray
NSPointerArray — это мутабельный массив, аналогичный NSArray, но он может хранить указатели с разными правилами памяти.
// Создаем массив, который будет хранить weak-ссылки
let weakArray = NSPointerArray.weakObjects()
let object = NSObject()
// Добавляем объект. NSPointerArray будет хранить weak-ссылку.
weakArray.addPointer(Unmanaged.passUnretained(object).toOpaque())
// Когда object будет деинициализирован, указатель в массиве станет nil.
// При получении объектов нужно быть осторожным с указателями.Подход с оберткой на чистом Swift часто предпочтительнее из-за большей типобезопасности и простоты.