Для чего в Swift используется явный захват self в замыканиях?

«Для чего в Swift используется явный захват self в замыканиях?» — вопрос из категории Swift Core, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Явный захват self в замыканиях необходим для предотвращения циклов сильных ссылок (retain cycles) и управления временем жизни объектов, особенно при работе с классами.

Проблема (сильный захват по умолчанию):

class DataManager {
    var data = [String]()

    func fetchData() {
        someAsyncTask {
            // Замыкание сильно захватывает `self`
            self.process(data: self.data) // Может создать retain cycle
        }
    }
}

Решение (слабый захват):

func fetchData() {
    someAsyncTask { [weak self] in // Слабый захват, не увеличивает счетчик ссылок
        guard let self = self else { return } // Проверка на существование
        self.process(data: self.data) // Безопасная работа
    }
}

Стратегии захвата:

  • [weak self]: Используйте почти всегда для асинхронных задач. Создает опциональную ссылку.
  • [unowned self]: Используйте только если уверены, что объект переживет замыкание. Приводит к крашу, если объект стал nil.
  • Value-типы (структуры, перечисления) не создают циклов, но явный захват self всё равно требуется для доступа к их методам и свойствам внутри замыкания.