Где хранится захваченная замыканием структура в Swift: в стеке или в куче?

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

Ответ

Место хранения зависит от типа замыкания:

  • Для non-escaping замыканий: Захваченная структура (тип-значение) обычно остается в стеке. Замыкание выполняется синхронно в пределах жизни функции, и нет необходимости продлевать время жизни захваченных значений.
  • Для @escaping замыканий: Захваченная структура копируется и хранится в куче. Это необходимо, потому что замыкание может быть вызвано после завершения функции, и его контекст (включая захваченные значения) должен оставаться валидным.

Почему так происходит? Swift автоматически управляет памятью для контекста замыкания. Если замыкание может "сбежать" из текущей области видимости, компилятор выделяет память в куче для всего его контекста.

Пример:

struct SensorData { var value: Double }

var data = SensorData(value: 25.5)

// 1. Non-escaping замыкание (стек)
func processImmediately(using closure: (SensorData) -> Void) {
    closure(data) // Вызывается здесь же
}

// 2. Escaping замыкание (куча)
var storedClosure: (() -> Void)?
func storeForLater(closure: @escaping () -> Void) {
    storedClosure = closure // Замыкание сохраняется и может быть вызвано позже
}

storeForLater { [data] in // `data` копируется в кучу
    print("Captured data: (data.value)")
}

Вывод: Структуры в @escaping замыканиях хранятся в куче, в non-escaping — обычно в стеке.