Как изменяется value type, захваченная замыканием в Swift, при повторном вызове замыкания?

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

Ответ

Поведение зависит от способа захвата value type (структуры, перечисления) в замыкании.

1. Захват по значению (capture list): Создается неизменяемая копия значения на момент создания замыкания.

var number = 10

// Захват текущего значения number
let closure = { [number] in
    print("Захваченное значение: (number)") // Всегда 10
    // number += 1 // Ошибка: 'number' is immutable
}

number = 20 // Изменяем оригинал
closure() // Вывод: "Захваченное значение: 10"
closure() // Вывод: "Захваченное значение: 10" (не изменяется)

2. Захват по ссылке (без capture list): Замыкание получает доступ к самой переменной, а не ее копии.

var counter = 0

let mutatingClosure = {
    counter += 1
    print("Счетчик: (counter)")
}

mutatingClosure() // Счетчик: 1
mutatingClosure() // Счетчик: 2
mutatingClosure() // Счетчик: 3

3. Изменение через inout параметр:

var value = 5

let inoutClosure = { (input: inout Int) in
    input += 10
}

inoutClosure(&value)
print(value) // 15

4. Использование класса-обертки для изменяемого захвата:

class Box<T> {
    var value: T
    init(_ value: T) { self.value = value }
}

var box = Box(100)
let boxClosure = { [box] in
    box.value += 1
    print(box.value)
}

boxClosure() // 101
boxClosure() // 102

Ключевой момент: Value types захватываются по значению по умолчанию. Для модификации между вызовами замыкания нужно использовать захват по ссылке или изменяемые обертки.