Ответ
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 гарантированно жив
}
Практические правила:
- Всегда используйте capture list (
[weak self],[unowned self]) для явного указания захватаselfво избежание retain cycles. - Захватывайте другие переменные через capture list, если важно явно показать зависимость замыкания или управлять их временем жизни (например,
[weak delegate]). weak selfвнутри тела замыкания без capture list — это ошибка. Capture list определяет, как захватывать, а использованиеself?внутри — это уже работа с захваченной ссылкой.
Итог: Capture list — это обязательный инструмент для безопасной работы с замыканиями, а weak self — его наиболее важный частный случай.
Ответ 18+ 🔞
А, capture list, ёпта! Ну это ж та самая штука, которая спасает от утечек памяти, когда замыкания начинают друг друга держать за жопу, как два пьяных мужика у подъезда — «я тебя не пущу, ты меня не пустишь», и оба в итоге в луже засыпают.
Смотри, суть-то проще, чем кажется. Вот представь: ты в баре, и твой друг self заказывает выпить. Если ты схватишь его в охапку и будешь держать как одержимый (сильный захват), он никуда не денется, даже если ему уже пора к семье. Но если он тебя попросит: «давай, брат, держи меня за рукав, на всякий» (weak capture), то он сможет уйти, когда захочет, а ты просто рукав в руках останется.
Пример 1: Классика — weak self
closure = { [weak self] in
self?.doWork() // Тут self — уже опциональный, как пропуск на закрытый завод.
}
Это и есть capture list, блядь! Ты явно говоришь: «захватываю self, но слабенько, чтобы он мог сдохнуть, если захочет».
Пример 2: А можно и не только self
class Processor {
var data: Data
var onComplete: (() -> Void)?
func process(with formatter: Formatter) {
// Смотри, какой красивый захват: self — слабо, а formatter — сильно.
someAsyncTask { [weak self, formatter] result in
guard let self = self else { return } // self проверяем, жив ли ещё
let output = formatter.format(result, using: self.data) // formatter тут как родной
self.finish(with: output)
}
}
}
Вот тут capture list уже не только self ловит, но и formatter. Зачем? Да чтобы явно видеть, от кого замыкание зависит, а то потом ищешь, блядь, где у тебя retain cycle, а он в какой-нибудь неочевидной переменной затаился, как шпион в сортире.
Пример 3: Переименование, чтоб не путать
networkService.fetchData { [weak self] result in
// Делаем сильную ссылку, но ТОЛЬКО локально, на время работы замыкания!
guard let strongSelf = self else { return }
strongSelf.handle(result)
strongSelf.cleanup() // И всё безопасно, strongSelf не сбежит.
}
Это как взять друга за рукав, а потом сказать: «ладно, иди сюда, посидим нормально», но только внутри этой комнаты. На улицу он уже не выйдет, пока вы не закончите.
Правила, блядь, правила:
- Всегда пиши capture list для self, если есть хоть малейший шанс на retain cycle. Не будь самоубийцей, который думает: «да ладно, пронесёт».
- Другие переменные тоже захватывай явно, если они важны. Особенно делегаты, сервисы — всякую шелупонь, которая может испариться.
weak selfбез capture list — это как пытаться открыть дверь без ключа, пинком. Не выйдет, компилятор тебя пошлёт нахуй. Capture list определяет, как захватить, аself?внутри — это уже использование того, что захватили.
Итог: Capture list — это не просто модная фича, а спасательный круг в море утечек памяти. А weak self — его главный поплавок. Используй, не ёби мозги себе и компилятору.