В чём разница между использованием capture list и просто weak self в замыкании?

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

Ответ

Capture list — это синтаксическая конструкция для явного управления захватом переменных в замыкании. [weak self] — это частный и самый распространённый случай capture list.

Ключевое отличие: Capture list позволяет контролировать захват любых переменных из окружающего контекста, а не только self. Она делает зависимости замыкания явными и предотвращает непреднамеренные сильные захваты.

Пример 1: Только weak self (это уже capture list)

closure = { [weak self] in
    self?.doWork()
}

Пример 2: Capture list с несколькими переменными

class Processor {
    var data: Data
    var onComplete: (() -> Void)?

    func process(with formatter: Formatter) {
        // Захватываем self слабо, а formatter сильно (по умолчанию).
        // Это явно показывает, что замыкание зависит от formatter.
        someAsyncTask { [weak self, formatter] result in
            guard let self = self else { return }
            let output = formatter.format(result, using: self.data)
            self.finish(with: output)
        }
    }
}

Пример 3: Захват с переименованием (например, сильная ссылка на self)

networkService.fetchData { [weak self] result in
    // Создаём сильную ссылку на self ТОЛЬКО на время выполнения замыкания
    guard let strongSelf = self else { return }
    strongSelf.handle(result)
    strongSelf.cleanup() // safe, strongSelf гарантированно жив
}

Практические правила:

  1. Всегда используйте capture list ([weak self], [unowned self]) для явного указания захвата self во избежание retain cycles.
  2. Захватывайте другие переменные через capture list, если важно явно показать зависимость замыкания или управлять их временем жизни (например, [weak delegate]).
  3. weak self внутри тела замыкания без capture list — это ошибка. Capture list определяет, как захватывать, а использование self? внутри — это уже работа с захваченной ссылкой.

Итог: Capture list — это обязательный инструмент для безопасной работы с замыканиями, а weak self — его наиболее важный частный случай.