При очистке массива экземпляров классов через removeAll(keepingCapacity:), когда экземпляры могут быть уничтожены?
При removeAll(keepingCapacity:) массив удаляет свои сильные ссылки на все элементы. Каждый экземпляр может быть уничтожен сразу после этого, если у него не осталось других сильных владельцев; сохранённая ёмкость буфера массива объекты не удерживает.
ARC автоматизирует управление временем жизни ссылочных типов с помощью подсчёта сильных ссылок. Это избавляет от ручных операций retain/release, но не отменяет необходимости понимать, какие структуры владеют объектами.
Для коллекций особенно важно различать память внутреннего буфера и ссылки на его элементы. Сохранение буфера предназначено для повторного использования памяти массива, а не для продления жизни удалённых объектов.
Разработчик может ошибочно решить, что keepingCapacity: true сохраняет элементы массива живыми, поскольку массив продолжает занимать память. В результате возникают неверные ожидания относительно момента вызова deinit и освобождения внешних ресурсов.
Реальный момент уничтожения каждого объекта зависит от всех его сильных ссылок. Само удаление элемента из массива лишь убирает один источник владения.
Array хранит экземпляры классов как сильные ссылки. При очистке массива ссылки на элементы удаляются, поэтому для каждого объекта ARC уменьшает счётчик сильных ссылок. Если счётчик достигает нуля, объект становится недоступен и его deinit запускается.
Параметр keepingCapacity влияет только на сохранение выделенного хранилища массива. Он позволяет избежать повторного выделения памяти при последующем добавлении элементов, но не оставляет удалённые элементы в массиве и не сохраняет их объекты.
После очистки массива объект ещё жив, потому что его удерживает item. keepingCapacity не меняет этот результат. После присваивания nil последняя сильная ссылка исчезает, и вызывается deinit.
Если внешней ссылки item нет, объект обычно может быть уничтожен во время очистки массива. Точный машинный момент освобождения не следует связывать с размером оставшегося буфера: ARC определяет время жизни по владению объектом, а не по занятой коллекцией памяти.
В приложении массив временно содержит изображения или сетевые дескрипторы, а затем очищается перед загрузкой следующей порции. Вариант с keepingCapacity: false освобождает ссылки на элементы и потенциально сам буфер; это уменьшает удерживаемую память, но последующие добавления могут потребовать нового выделения.
Вариант с keepingCapacity: true сохраняет буфер и обычно выгоден при многократном заполнении массива примерно одинакового размера. Он не мешает уничтожению изображений или дескрипторов, если массив был их последним сильным владельцем. Поэтому выбранный вариант зависит от компромисса между повторным использованием ёмкости и памятью самого буфера, но не от требования удерживать элементы живыми.
removeAll немедленный вызов deinit каждого элемента?Нет. Он удаляет сильные ссылки массива, но объект может оставаться живым из-за локальной переменной, другого массива, свойства, замыкания или иной сильной ссылки. deinit вызывается только после исчезновения последнего сильного владельца.
keepingCapacity число сильных ссылок на элементы?Нет. Этот параметр управляет только вместимостью внутреннего хранилища коллекции. После очистки в массиве нет доступных элементов, а ссылки на прежние элементы не должны продолжать удерживаться ради сохранения ёмкости.
Нет. Уничтожение объектов и возврат памяти операционной системе — разные события. ARC может вызвать deinit и освободить память объекта, но аллокатор способен оставить освобождённые страницы внутри процесса для повторного использования, поэтому RSS может не уменьшиться сразу.