Ответ
Замыкание (closure) — это самодостаточный блок функциональности (функция), который может захватывать и хранить ссылки на переменные и константы из окружающего контекста, даже после того как этот контекст перестал существовать. В Swift замыкания являются first-class типами: их можно передавать как аргументы, возвращать из функций и присваивать переменным.
Пример создания и использования:
// Функция, возвращающая замыкание
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
// Замыкание захватывает runningTotal и amount
let incrementer: () -> Int = {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTwo = makeIncrementer(forIncrement: 2)
print(incrementByTwo()) // 2
print(incrementByTwo()) // 4
// Каждое замыкание хранит свое собственное состояние runningTotal
let anotherIncrementer = makeIncrementer(forIncrement: 2)
print(anotherIncrementer()) // 2 (независимое состояние)
Ключевые особенности и best practices:
- Захват по ссылке: Захваченные переменные (как
runningTotal) хранятся в куче, что позволяет замыканию жить дольше своей области видимости. -
Циклы сильных ссылок (Retain Cycles): Замыкания, захватывающие
selfили экземпляры классов, могут создавать циклы удержания памяти. Для их предотвращения используйте списки захвата:class MyViewController { var handler: (() -> Void)? func setupHandler() { // Используйте [weak self] или [unowned self] handler = { [weak self] in guard let self = self else { return } self.doSomething() } } } - Синтаксический сахар: Swift предлагает упрощенный синтаксис (trailing closures, shorthand argument names
$0,$1). - Автозамыкания (
@autoclosure): Позволяют отложить выполнение выражения, оборачивая его в замыкание автоматически. Часто используется для условной оценки (например, вassert). @escaping: Помечает замыкание, которое может быть вызвано после возврата из функции (например, в асинхронных колбэках).