Вступить в клуб →
средняявопросАрхитектура и состояние экрана

У ViewModel не вызывается deinit после закрытия экрана

Экран ленты на iOS:

final class FeedViewModel {
    private let service: FeedService
    private var cache: [Post] = []
    var onUpdate: (([Post]) -> Void)?

    func subscribe() {
        service.observe { posts in
            self.cache = posts
            self.onUpdate?(posts)
        }
    }
}

Сервис хранит переданное замыкание у себя, пока подписка активна. Экран закрывают, но брейкпоинт в deinit у ViewModel не срабатывает, а обновления продолжают приходить.

В чём причина?

  • Замыкание, которое удерживает сервис, сильно захватывает self — возникает цикл сильных ссылок, нужен захват [weak self]
  • deinit не вызывается у классов с активными асинхронными подписками — это ожидаемое поведение среды выполнения, объект освободится позже сам
  • Причина в том, что onUpdate объявлено как var: опциональные замыкания всегда удерживают своего владельца
  • Объект не освобождается, потому что класс не наследуется от NSObject и не отслеживается механизмом подсчёта ссылок

🔒 Проверка ответа — для участников клуба

  • Проверка ответа
  • Подсказка, если застряли
  • Разбор с объяснением, почему так
  • Прогресс по всем задачам и виртуальные собеседования
Зарегистрироваться →

Регистрация занимает минуту

Другие задачи раздела