Циклы и перебор коллекций

Циклы позволяют повторять действия: пройти по списку задач, просуммировать числа, обработать каждый элемент.
Суть урока: в Swift основной инструмент — for-in. Он напрямую перебирает элементы коллекции, не возясь с индексами, что делает код чище и безопаснее.

Самый частый цикл — for-in. Он берёт каждый элемент коллекции по очереди:

let names = ["Анна", "Борис", "Вера"]
for name in names {
    print("Привет, \(name)")
}

for number in 1...5 {        // по диапазону
    print(number * number)
}

Если нужны и индекс, и значение — есть enumerated(). А для перебора с шагом — stride:

for (index, name) in names.enumerated() {
    print("\(index): \(name)")
}

for even in stride(from: 0, to: 10, by: 2) {
    print(even)   // 0, 2, 4, 6, 8
}

Словарь перебирается парами ключ-значение:

let scores = ["Анна": 95, "Борис": 88]
for (name, score) in scores {
    print("\(name) набрал \(score)")
}

Когда число повторов заранее неизвестно, помогает while (проверка до тела) и repeat-while (тело хотя бы раз, потом проверка):

var countdown = 3
while countdown > 0 {
    print(countdown)
    countdown -= 1
}
print("Старт!")

Попробуй сам ▶ — запусти код прямо в браузере (Pyodide). Здесь нет Swift, но логика та же, что под капотом мобильного кода:

# for-in, enumerate и while — всё это есть и в Python, логика та же.
names = ['Анна', 'Борис', 'Вера']
for i, name in enumerate(names):   # как .enumerated()
    print(i, name)

for even in range(0, 10, 2):       # как stride(from:to:by:)
    print('чёт', even)

countdown = 3
while countdown > 0:
    print(countdown)
    countdown -= 1
print('Старт!')

Как работает под капотом

За for-in стоит протокол Sequence и его итератор: цикл вызывает next(), пока не получит nil. Это значит, что перебирать можно не только массивы, но и любые типы, которые реализуют этот протокол — диапазоны, строки (по символам), даже собственные структуры. Перебор по элементам, а не по индексам, исключает классическую ошибку «выход за границу» и делает код декларативнее.

Частые ошибки

  • Менять коллекцию во время её перебора. Добавление или удаление элементов внутри for-in приводит к непредсказуемому поведению.
  • Бесконечный while. Забыли изменить условие — цикл не закончится и приложение зависнет.
  • Городить ручные индексы там, где хватит for-in. Это лишний код и риск ошибки.

Best practices

  • Предпочитайте for-in циклу по индексам; используйте enumerated(), когда индекс действительно нужен.
  • Для досрочного выхода используйте break, для пропуска итерации — continue.
  • Если цикл лишь преобразует данные — присмотритесь к map/filter из следующего урока.

Итоги. for-in — главный цикл Swift, он перебирает элементы напрямую и работает с любой последовательностью. while и repeat-while нужны, когда число повторов неизвестно. Скоро вы увидите, что многие циклы элегантнее заменить функциональными методами.

Шире контекста

Понимание протокола Sequence за циклом for-in открывает целый мир. Перебирать можно не только массивы, но и диапазоны, строки посимвольно, ключи и значения словаря, и даже ваши собственные типы, если они умеют выдавать элементы по одному. Это объясняет, почему один и тот же синтаксис цикла работает с таким разным содержимым — за ним стоит единый контракт. Со временем вы заметите интересную закономерность: чем опытнее становится разработчик, тем реже он пишет явные циклы. Многие задачи, которые новичок решает циклом с накоплением результата, элегантнее выражаются через map, filter и reduce из следующего урока. Циклы остаются незаменимы там, где есть побочные эффекты или сложное управление потоком с break и continue, но привычка спрашивать себя «а нельзя ли это выразить декларативно?» — важный шаг к зрелому, читаемому коду в стиле SwiftUI.

Проверьте себя
1. Какой метод даёт одновременно индекс и значение при переборе массива?
Aindices()
Benumerated()
Cstride()
Dzip()
2. Чем repeat-while отличается от while?
AНичем
Brepeat-while выполняет тело хотя бы один раз до проверки условия
Crepeat-while работает только с числами
Dwhile быстрее