Вступить в клуб →
сложнаявопросSwift: типы, опционалы и ARC

Экран закрыт, но tick продолжает срабатывать и deinit не вызывается

Экран плеера обновляет прогресс раз в секунду.

final class PlayerViewController: UIViewController {
    private var timer: Timer?

    override func viewDidLoad() {
        super.viewDidLoad()
        timer = Timer.scheduledTimer(timeInterval: 1,
                                     target: self,
                                     selector: #selector(tick),
                                     repeats: true)
    }

    @objc private func tick() { }

    deinit { timer?.invalidate() }
}

Пользователь уходит с экрана, но deinit не вызывается, а tick продолжает срабатывать. В чём причина и что исправит ситуацию?

  • Таймер удерживается RunLoop и сам сильно держит target: invalidate нужно звать при уходе с экрана
  • Достаточно объявить свойство как weak var timer — тогда таймер освободится вместе с контроллером
  • Нужно заменить target/selector на вариант с замыканием и [weak self]; после этого invalidate не понадобится вовсе
  • Проблема в @objc-методе: селектор удерживает контроллер, поэтому tick нужно сделать статическим

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

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

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

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