Назад к вопросам
Middle
100
questionbank

Объясните разницу между escaping и non-escaping closures, и в каких случаях необходимо использовать @escaping.

Sobes Copilot

Получайте ответы в реальном времени

Ответ от нейросети

sobes.tech AI

Замыкания по умолчанию являются non-escaping.

Non-escaping closure:

  • Выполняется в теле функции, которой передается.
  • Захватывает переменные, но освобождает их после завершения функции.
  • Не переживает функцию.
func doSomething(completion: () -> Void) {
    // Вызов completion здесь
    completion() 
}

Escaping closure:

  • Выполняется после возврата функции, которой передается.
  • Переживает тело функции.
  • Может быть сохранено для последующего выполнения, например, в другом потоке или асинхронно.
  • Захватывает переменные, сохраняя сильные ссылки, что может привести к циклам сильных ссылок (retain cycles). Требует явного указания @escaping.
class DataManager {
    var completionHandlers: [() -> Void] = []

    func addCompletionHandler(handler: @escaping () -> Void) {
        completionHandlers.append(handler)
    }

    func performTasks() {
        // Выполнение задач...
        for handler in completionHandlers {
            handler() // Вызов хэндлеров позже
        }
    }
}

Использование @escaping необходимо в следующих случаях:

  • Когда замыкание сохраняется в свойстве класса или структуры.
  • Когда замыкание передается другому потоку или асинхронной операции (например, сетевой запрос, GCD, OperationQueue).
  • Когда замыкание используется в качестве обработчика события или делегата.