В третьей лекции обновленного курса Stanford CS193p (весна 2025 года) основной фокус смещается с визуального конструирования интерфейса на внутреннюю архитектуру приложений и фундаментальные основы языка Swift. Профессор Стэнфордского университета подробно разбирает концепцию разделения модели и интерфейса, а также глубоко погружается в систему типов, объясняя работу замыканий, перечислений и опциональных значений.
🛠️ Функциональное программирование и магия замыканий в Swift 1:41
В начале занятия лектор возвращается к коду функции matchMarker(), чтобы продемонстрировать возможности синтаксического сахара Swift при работе с функциями высшего порядка . Основная задача — подсчитать количество точных совпадений в массиве.
Эволюция кода от громоздкого к лаконичному проходит через несколько этапов:
- Использование явного возврата
returnvs атрибут@ViewBuilder. - Применение тернарного оператора (
? :) для компактной логики внутри модификаторов . - Переход от именованных функций (например,
isExact()) к инлайновым замыканиям (inline closures) .
Особое внимание уделяется ключевому слову in, которое служит разделителем между описанием аргументов и телом функции . В конечном итоге код сокращается до использования сокращенных имен параметров, таких как $0, что делает функциональное программирование в Swift крайне выразительным . По словам лектора, программирование путем передачи функций другим функциям — это база, которую студенты будут использовать десятки раз на протяжении курса .
🏗️ Архитектура: Модель против Интерфейса (Model vs UI) 16:52
Данные в приложении должны течь из «Модели» (логика приложения) через «UI» (интерфейс) к органам чувств пользователя . SwiftUI строго разделяет эти уровни.
Основные принципы архитектуры по мнению автора курса:
- Модель — это сердце приложения. Она содержит данные и логику (например, правила игры CodeBreaker), независима от интерфейса и может представлять собой структуры, базы данных SQL или API .
- Интерфейс — это визуальное проявление модели. UI в SwiftUI является декларативным (мы описываем, что хотим видеть) и реактивным (он автоматически обновляется при изменении модели) .
- Единственный источник истины (Source of Truth). Данные не должны дублироваться . Для управления состоянием используются специальные инструменты, такие как
@State.
💎 Система типов: Почему структуры лучше классов? 23:46
Swift предлагает две основные категории типов: значимые (Value types — структуры и перечисления) и ссылочные (Reference types — классы) . Это фундаментальное различие определяет, как данные ведут себя при передаче в функции.
Преимущества структур (Structs):
- Иммутабельность по умолчанию. Значение хранится непосредственно в переменной .
- Безопасность. При передаче структуры создается ее копия (Copy on Write), что исключает случайное изменение данных из другого участка кода .
- Явное изменение. Мутабельность должна быть обозначена ключевым словом
varили атрибутом@State.
Классы (Classes) используются реже и в основном там, где необходимо совместное использование (sharing) данных или четкая идентичность объекта (identity) через указатель в памяти . Лектор отмечает, что SwiftUI-вью — это всегда структуры, так как система постоянно пересоздает их «тела» (var body) при изменениях, что было бы крайне неэффективно с классами .
📦 Перечисления (Enums) и ассоциированные данные 41:23
Перечисления в Swift — это не просто список констант, а мощный инструмент моделирования данных. Самая важная их особенность — ассоциированные данные (associated data) .
Примеры использования:
- Кейс
hamburgerв перечисленииFastFoodMenuItemможет хранить количество котлет (patties: Int) . - Кейс
drinkможет содержать одновременно бренд (String) и объем в унциях (Double) .
Для извлечения этих данных используется конструкция switch, которая в Swift обязана быть исчерпывающей (должна обрабатывать все возможные варианты) . Также упоминается протокол CaseIterable, который автоматически создает свойство allCases, позволяя итерироваться по всем пунктам перечисления .
❓ Optionals: Как Swift борется с «ничем» 54:05
В Swift каждая переменная обязана иметь значение. Optional — это решение для ситуаций, когда значение может отсутствовать (состояние «не определено» или «невалидно») .
Технически Optional — это перечисление с двумя состояниями: .none (оно же nil) и .some (содержит ассоциированное значение любого типа) . Лектор подчеркивает, что Swift использует дженерики (Generics), чтобы Optional мог работать с любым типом данных .
Способы работы с опционалами:
- Force Unwrapping (
!): «Жесткое» извлечение. Если внутриnil, приложение упадет. По мнению лектора, это допустимо при разработке для выявления ошибок, но опасно в продакшене . - Optional Binding (
if let): Безопасный способ проверить наличие значения и сразу начать с ним работать . - Nil-coalescing (
??): Установка значения по умолчанию, если опционал пуст .
🧩 Расширения (Extensions) и провальные инициализаторы 1:04:39
В завершение лекции обсуждаются способы расширения функциональности. Провальные инициализаторы (init?) позволяют вернуть nil, если объект не может быть создан с данными параметрами (например, если мы пытаемся создать цвет из несуществующей строки) .
Механизм extension позволяет добавлять методы и вычисляемые свойства даже к тем типам, исходного кода которых у разработчика нет (например, к системному классу Color или протоколу View) . Это ключевой инструмент для декомпозиции кода и добавления удобных модификаторов в SwiftUI .