День 15 — Повторение Swift
За две недели мы прошли основные строительные блоки языка. Сегодня не добавляем крупную тему, а связываем знания в одну картину. Если какая-то часть кажется размытой, вернитесь к соответствующему уроку и измените пример своими руками.
Значения и типы
let appName = "Habit" // String, менять нельзя
var streak = 7 // Int, можно менять
let progress: Double = 0.7
let isPremium = false // Boolletиспользуйте по умолчанию;var— когда значение действительно меняется;- type inference выводит тип из начального значения;
- type annotation выбирает или документирует конкретный тип.
Коллекции и enums
let orderedTasks = ["Код", "Тест", "Commit"]
let scores = ["Анна": 10, "Иван": 8]
let uniqueTags: Set = ["swift", "ios"]
enum Status {
case idle
case loading
case loaded(count: Int)
case failed(message: String)
}Array сохраняет порядок, Dictionary связывает ключ и значение, Set обеспечивает уникальность. enum моделирует конечные состояния и может хранить associated values.
Условия и циклы
let score = 82
if score >= 80 {
print("Отлично")
} else {
print("Продолжаем")
}
for number in 1...3 {
print(number)
}switch особенно полезен вместе с enum, потому что компилятор проверяет полноту вариантов.
let status = Status.loaded(count: 12)
switch status {
case .idle:
print("Ожидание")
case .loading:
print("Загрузка")
case .loaded(let count):
print("Получено: \(count)")
case .failed(let message):
print(message)
}Functions и errors
enum ValidationError: Error {
case emptyName
}
func normalizedName(_ name: String, uppercase: Bool = false) throws -> String {
let trimmed = name.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else {
throw ValidationError.emptyName
}
return uppercase ? trimmed.uppercased() : trimmed
}Функция получает вход через параметры, возвращает результат и при необходимости выбрасывает ошибку. Labels делают место вызова естественным, defaults упрощают частый сценарий, tuple возвращает небольшой фиксированный набор значений.
Closures
let numbers = [5, 2, 8, 1]
let labels = numbers
.filter { $0 > 2 }
.sorted()
.map { "Значение: \($0)" }Closure — функция-значение. Она может быть аргументом, результатом или сохранённой переменной. Trailing closure syntax делает вызовы с поведением компактными и лежит в основе синтаксиса SwiftUI.
Structs и classes
struct Profile {
let id: Int
var name: String
var displayName: String {
name.isEmpty ? "Гость" : name
}
mutating func rename(to newName: String) {
name = newName
}
}Struct — value type: при присваивании создаётся независимое значение. Class — reference type: несколько переменных могут наблюдать один объект. Начинайте со struct и выбирайте class для общей идентичности, inheritance или class-based API.
Protocols и extensions
protocol Summarizable {
var summary: String { get }
}
extension Summarizable {
func printSummary() {
print(summary)
}
}
extension Profile: Summarizable {
var summary: String {
"#\(id): \(displayName)"
}
}Protocol задаёт контракт. Extension добавляет возможности существующему типу. Protocol extension предоставляет общее поведение множеству несвязанных типов.
Optionals
func printFirst(_ names: [String]?) {
guard let first = names?.first else {
print("Список пуст")
return
}
print(first)
}Основные инструменты:
if let— извлечь значение в локальной ветке;guard let— проверить обязательное значение и выйти раньше;??— выбрать разумный fallback;?.— безопасно продолжить цепочку;try?— превратить ошибку в отсутствие результата, если причина не нужна.
Как всё соединяется
Небольшой пример использует сразу несколько тем:
protocol Describable {
var description: String { get }
}
struct Task: Describable {
let title: String
var isDone = false
var description: String {
"\(isDone ? "✓" : "○") \(title)"
}
mutating func complete() {
isDone = true
}
}
var tasks: [Task] = [
Task(title: "Повторить closures"),
Task(title: "Собрать первый экран")
]
tasks[0].complete()
for task in tasks {
print(task.description)
}Здесь Array хранит models, struct задаёт собственный value type, protocol описывает способность, computed property формирует строку, mutating method меняет состояние, цикл выводит элементы, а ternary operator выбирает значок.
Самопроверка
Попробуйте ответить без запуска кода:
- Почему
letпредпочтительнееvar, если изменение не нужно? - Чем
0..<5отличается от0...5? - Когда Dictionary подходит лучше Array?
- Почему throwing function вызывают с
try? - Что получает closure в
sorted(by:)и что возвращает? - Чем computed property отличается от stored property?
- Почему копия struct меняется независимо, а class — нет?
- Как protocol extension уменьшает повторение?
- Как безопасно получить первое значение optional Array?
Если можете объяснить ответы своими словами и написать небольшой пример, базовый синтаксис уже на месте. Новые темы будут появляться позже прямо перед проектом, в котором понадобятся.
Следующий шаг
Переходите прямо к Project 1 — WeSplit. Testing, Observation, generics и concurrency встретятся позже just-in-time, когда у каждой темы появится практическая задача.
Мини-проект перед SwiftUI
Соберите консольный трекер задач: Array из Task, функции добавления и завершения, enum для фильтра, вывод через closure-сортировку. Не копируйте пример целиком — сначала запишите требования и выберите типы самостоятельно.
Что запомнить
Синтаксис забывается и быстро восстанавливается. Гораздо важнее понимать модель: какие состояния допустимы, кому принадлежит изменение и как типы помогают исключить ошибки.
🎉 Базовый синтаксис Swift пройден
До этого момента ты изучал сам язык Swift: переменные, Arrays, условия, functions, structs, protocols, optionals и другие базовые возможности.
Теперь начинается SwiftUI. Это не новый язык: знакомый Swift никуда не исчезает. SwiftUI постоянно использует его, чтобы описывать интерфейс и реакцию на действия пользователя.
🧠 Разберём через знакомое
Уже знакомо
- Swift✓ let и var
- Swift✓ Double
- Swift✓ Arrays
- Swift✓ Ranges
- Swift✓ Closures
- Swift✓ Structs
- Swift✓ Computed properties
- Swift✓ Protocols
- Swift✓ Optionals
Новое
- SwiftUI→ View
- SwiftUI→ @State
- SwiftUI→ Form
- SwiftUI→ Section
- SwiftUI→ NavigationStack
- SwiftUI→ Picker
- SwiftUI→ TextField
- SwiftUI→ ForEach
В первом проекте:
- Array наполнит варианты
Picker; - Range и closure построят строки
ForEach; struct ContentViewстанет экраном;- computed property рассчитает сумму;
- protocol
Viewсвяжет структуру со SwiftUI; - Optional поможет выбрать формат валюты.
Комментарии
Вопросы, находки и подсказки по этой странице.
Войди, чтобы задать вопрос или помочь другим.