Какие stored-свойства экземпляра ещё доступны внутри его deinit?
В момент выполнения deinit stored-свойства экземпляра ещё доступны: тело deinit выполняется до окончательного освобождения хранилища объекта. После завершения deinit Swift уничтожает оставшиеся свойства и освобождает память экземпляра.
Это не означает, что объект можно продлить или безопасно передать наружу. deinit — финальная стадия жизни экземпляра, поэтому его задача — освободить ресурсы, а не продолжать обычную работу объекта.
ARC автоматизирует управление временем жизни объектов, но не может угадать, какие внешние ресурсы нужно закрыть: файлы, соединения, дескрипторы или подписки. Для детерминированного освобождения таких ресурсов в Swift существует deinit.
Чтобы очистка была предсказуемой, объект сначала должен выполнить пользовательскую логику завершения, а уже затем его хранилище и свойства могут быть разрушены. Поэтому deinit предоставляет доступ к состоянию экземпляра, необходимому для корректной очистки.
Ошибка возникает, когда разработчик считает, что к моменту входа в deinit свойства уже недоступны, либо, наоборот, пытается использовать экземпляр после завершения deinit. В первом случае можно преждевременно отказаться от нужной очистки, во втором — получить обращение к уже уничтожаемому объекту.
Особенно важно учитывать свойства-ссылки: пока выполняется тело deinit, их уничтожение ещё не завершено. Однако вызов методов других объектов из deinit может запускать сложную логику, повторные освобождения или обращения к объектам, которые уже находятся в процессе завершения.
Порядок можно представить так: ARC определяет, что сильных владельцев больше нет; запускается deinit; выполняется его тело; затем Swift разрушает stored-свойства и завершает освобождение экземпляра. В deinit можно читать и изменять доступные свойства, если это разрешено обычными правилами доступа.
Внутри deinit нельзя рассчитывать на продление жизни текущего объекта. Нельзя превращать финальную очистку в обычный публичный метод или безопасно сохранять self для последующего использования: объект уже проходит необратимую фазу разрушения.
Свойства-ссылки, которыми владел экземпляр, обычно освобождаются после выполнения тела его deinit. Их освобождение может уменьшить счётчик сильных ссылок на другие объекты и запустить их собственные deinit, поэтому код очистки должен быть коротким, предсказуемым и не зависеть от сложного порядка побочных эффектов.
В примере identifier и connection доступны в deinit. После завершения его тела свойство connection будет уничтожено как часть разрушения Session; если это была последняя сильная ссылка на соединение, может запуститься и его финализация.
Компонент приложения хранит сетевое соединение и должен закрыть его при уничтожении. Вариант с вызовом close() только в deinit прост и подходит, если время освобождения компонента полностью контролируется ARC. Его минус — deinit не вызывается в ожидаемый момент при наличии цикла ссылок или другой сильной ссылки.
Вариант с отдельным методом stop() даёт явный контроль и позволяет закрыть соединение до уничтожения объекта. Но он требует дисциплины вызова и защиты от повторного выполнения. На практике выбирают явный stop() для бизнес-критичного завершения работы, а deinit оставляют как резервную очистку ресурсов и диагностику утечек.
Если в deinit вызывается метод свойства, нужно проверить его потокобезопасность и отсутствие обратного удержания владельца. Иначе финализация может породить гонку или сохранить другой объект дольше ожидаемого.
deinit обычным способом освобождения ресурса?Нет. deinit вызывается только тогда, когда ARC определил отсутствие сильных ссылок на экземпляр. Его момент зависит от графа владения, поэтому для операций, которые должны завершиться немедленно, лучше использовать явный метод закрытия или специальный объект-обёртку с предсказуемым управлением ресурсом.
Пока тело deinit текущего объекта выполняется, его stored-свойства ещё существуют. Освобождение сильного property после этого может стать последней операцией владения другим объектом и запустить его deinit. Поэтому порядок побочных эффектов может быть вложенным: завершение одного объекта способно немедленно начать завершение другого.
deinit безопасно запустить асинхронную очистку с захватом self?Нет, захват self для работы после завершения deinit противоречит жизненному циклу объекта. Асинхронная задача должна получить независимое состояние или отдельный ресурс, а не ссылку на уничтожаемый экземпляр. Иначе возможны ошибка компиляции, некорректное удержание или обращение к состоянию объекта после начала его разрушения.