unowned self опасен: контроллер может исчезнуть за 20 секунд, а callback позже обратится к освобождённому объекту. asyncAfter не блокирует главный поток на это время.
Найдите дефекты в Swift‑коде
unowned self опасен: контроллер может исчезнуть за 20 секунд, а callback позже обратится к освобождённому объекту. asyncAfter не блокирует главный поток на это время.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
В задании требуется проанализировать представленный фрагмент Swift‑кода и указать потенциальные проблемы, связанные с управлением памятью и жизненным циклом объектов. Обратите внимание на использование unowned и длительные задержки в главном потоке.
class Service {
func fetchData(completion: @escaping (String) -> Void) {
DispatchQueue.main.asyncAfter(deadline: .now() + 20.0) {
completion("hello world")
}
}
}
class ViewController: UIViewController {
let dataService = Service()
let outputLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
dataService.fetchData { [unowned self] (result) in
self.outputLabel.text = result
}
}
}
Ответ
unowned self опасен: контроллер может исчезнуть за 20 секунд, а callback позже обратится к освобождённому объекту. asyncAfter не блокирует главный поток на это время.
Замените захват на [weak self] и обновляйте self?.outputLabel.text, если экран ещё существует. В этом примере callback уже приходит на main queue, поэтому дополнительное переключение очереди не нужно. Таймер лишь планирует исполнение не раньше указанного срока, а не заставляет поток спать. Для реального запроса полезны отмена при закрытии экрана и проверка актуальности результата. unowned допустим только при гарантии, что контроллер переживёт callback; здесь такой гарантии нет.