Стэнфордский курс CS193P “Разработка iOS приложений в SwiftUI” Весна 2023: русскоязычный конспект с адаптацией к iOS 17
Если вы хотите получить фундаментальные знания по разработке iOS приложений с помощью SwiftUI
, вам следует пройти стэнфордский курс CS193P. Предложенные в весеннем семестре 2023 года лекции Стэнфордского курса CS193P «Developing Application for iOS with SwiftUI» («Разработка приложений для iOS с использованием SwiftUI») — это уже 3-я реинкарнация курса CS193P с фреймворком SwiftUI
. На сайте курса вы найдете материалы, которые были предоставлены студентам Стэнфорда в течение весеннего семестра 2023 г.: ссылки на видео, слайды, домашние задания и код демонстрационных примеров для iOS 16
и Xcode 14
.
На данный момент конспекты этого курса на русском языке находятся в открытом доступе:
В настоящий момент действуют Xcode 15 / iOS 17, которые были представлены на WWDC 2023 уже после завершения курса CS193P, наиболее значимое обновление внесено в механизм реактивного UI в SwiftUI
(макрос @Observable против протокола ObservableObject
). Тем не менее, ObservableObject
присутствует в Xcode 15 / iOS 17, и может использоваться совместно с новым макросом @Observable.
В иллюстрированных русскоязычных конспектах этого курса сделаны пометки, касающиеся изменений в iOS 17, а также восполнены некоторые фрагменты Лекций, где есть звук, но пропадает изображение, когда профессор демонстрирует что-то «в живую». Для большинства Лекций представлена версия с использование макроса @Observable вместо протокола ObservableObject
, в ряде случаев это потребовало нетривиальных решений.
Профессор придерживается “повествовательного” (Narrative) способа обучения работе с такой системой, как SwiftUI
. Этот способ заключается в том, что вы изучаете всех “персонажей” и настройки SwiftUI
, попутно следуя какому-то сюжету, и строите новый мир, постепенно добавляю в него все новые и новые кусочки кода. И не просто добавляются какие-то несвязанные фрагменты кода, a появление любой строчки кода четко объясняется сюжетом разрабатываемого приложения. В результате перед вами предстает полная картина разработки iOS приложений. Именно так профессор рассказывает историю разработки приложения на SwiftUI
.
Традиционно в этом курсе представлена разработка всего двух приложений. Первое — это карточная игра “на совпадение” Memorize для iPhone (Лекции 1-9), a второе — приложение Emoji Art для создания “картин” из эмодзи (смайликов) и фоновых изображений, скачиваемых из Интернета, для iPad и Mac (Лекции 10-15).
Игра Memorize имеет довольно простую логику и один экран, на котором всё и происходит: сама игра и подсчет очков. В ней нет ни навигации, ни сложных жестов, ни всплывающих окон, ни многопоточности. Но она призвана отточить ваши основные навыки программирования в Swift
и проектирования Reactive UI в SwiftUI
- система ТИПов Swift
, протоколы protocol
, Generics
, расширения extension
, Optional
, архитектуру MVVM + MVI
, @ViewBuilder, Layout
, ViewModifier
, неявная (implicit
) и явная (explicit
) анимации, переходы Transition
, TimelineView
, matchedGeometryEffect
.
Второе приложение Emoji Art - более сложное приложение для создания произведений искусства в виде картин из эмодзи и фоновых изображений, выбираемых из интернета и размещаемых с помощью механизма Drag & Drop. Здесь уже две MVVM: одна - для самой картины, a другая - для хранилища палитр, которое можно редактировать, причем вторая модель Model для палитр предоставляется вашему View
напрямую, но при этом ViewModel
остаётся, и Пол Хэгерти объясняет почему. В этом приложении уже есть и новая навигация, и новая многопоточность с использованием actor
, сочетание жестов Pan
и Pinch
с @GestureState, a также использование файловой системы iOS и UserDefaults
для постоянного хранения и т.д. Финальная версия этого приложения вообще является документо-ориентированным приложением.
Хотя структура курса CS193P Spring 2023 во многом аналогична версии CS193P Spring 2021, содержание сильно отличается, поскольку SwiftUI существенно усовершенствовался за эти 2 года: изобретены новые “комбинирующие” View
(LazyVGrid
, LazyHGrid
), которые вдохновили на создание собственного AspectVGrid
, расширились возможностей Shape
, появились новые View
модификаторы (.onChange
) и "Обертки” Свойств (@FocusState), новые виды анимации (TimelineView
, matchedGeometryEffect
), существенно упростилось выполнение Drag & Drop за счет нового протокола Transferable
, изменилась концепция навигации (NavigationStack
/ SplitView
, NavigationLink
, .navigationDestination
), появилась абсолютно новая концепция многопоточности. Профессор даже использует более современный вариант многозадачности на iPad - Stage Manager.
Каждая тема прорабатывается троекратно: сначала профессор рассказывает проблему на слайдах, потом показывает в демонстрационном примере и, наконец, вы закрепляете ее, выполняя Домашнее Задание, которых в курсе 6.
Кроме того в курсе есть так называемые “Задания на чтение”, их 3, которые, по сути, являются руководством к тому, как рационально изучить язык программирования Swift
за короткое время.
Слушать Лекции лучше всего, параллельно программируя в Xcode
. Именно в этом состоит Домашнее Задание # 1, и тут вам реально может пригодиться русскоязычный иллюстрированный конспект, ибо не нужно перематывать Video туда-сюда, и весь материал у вас под рукой.
Вот краткое содержание Лекций курса «Developing Application for iOS with SwiftUI Spring 2023»
Лекция 1. Начало работы со SwiftUI.
Введение в курс. Основы SwiftUI
. Начинаем работать над первым приложением этого семестра — карточной игрой под названием Memorize. Это будет основой учебного материала для первых нескольких недель курса. Демонстрация основ композиции элементов пользовательского интерфейса (UI), используемой в SwiftUI
, происходит в среде разработки Xcode.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 1.
Задание на чтение 1.
Лекция 2. Больше о SwiftUI.
Разработка игры Memorize продолжается. Создание пользовательских View
. Обработка жеста касания TapGesture
. Добавление кнопок Button
. Факторизация повторяющегося кода.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 2.
Задание на программирование 1.
Лекция 3. MVVM.
Концептуальный обзор архитектурной парадигмы, лежащей в основе разработки iOS приложений с использованием SwiftUI
, известной как MVVM. Объяснение фундаментального компонента понимания языка программирования Swift
: его системы ТИПов. Начинаем применять это для игры Memorize.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 3.
Лекция 4. Применение MVVM.
Применяем архитектуру MVVM к приложению Memorize. Попутно познакомимся с дженериками (Generics
) и получим представление о static
переменных и функциях. Создание реактивного UI. Продолжим изучать возможности Xcode.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 4.
Задание на чтение 2
Лекция 5. Протоколы protocol, перечисления enum, Optional
Основная тема — протоколы (Identifiable
, Equatable
и т. д.). Кроме того, рассматривается ещё один важный элемент системы ТИПов в Swift
— перечисление enum
. Много внимания уделено самому важному перечислению enum
в Swift
— Optional
. Логика Memorize завершается использованием вычисляемых свойств.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 5.
Задание на программирование 2.
Лекция 6. Расположение на экране Layout, @ViewBuilder
Как SwiftUI
отображает свои Views
, учитывая доступное ему пространство? И как мы можем создать свои собственные «механизма компоновки» Views
? Обновление игры Memorize, чтобы максимально эффективно размещать любое количество карт на экране без прокрутки. «Закулисье» @ViewBuilder, используем @ViewBuilder для вычисляемых переменных, в инициализаторах init
для аргументов-функций и переменных var
в структурах struct
.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 6.
Задание на чтение 3
Задание на программирование 3.
Код AspectVGrid.swift.
Лекция 7. Геометрические фигуры Shape, модификаторы ViewModifier, константы Constants
Как рисовать геометрические фигуры Shape
в SwiftUI
(например, геометрическую фигуру в виде «пирога» Pie
, необходимую для будущей анимационной «фичи» игры Memorize). Как создавать собственные модификаторы ViewModifier
(например, тот, который «картифицирует» (то есть превращает в карту) любое View
, а не только нашу игровую карту Memorize). Попутно представим формализм для аккуратного добавления констант в наш код.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 7.
Код Cardify.swift.
Код Pie.swift.
Лекция 8. Анимация (часть 1)
Первая часть анимационного приключения, состоящего из двух частей. Неявная (implicit
) анимация против явной (explicit
) анимации. Кривые анимации. Анимация модификатора ViewModifier
(переворот карт).
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 8.
Задание на чтение 4.
Лекция 9. Анимация (часть 2)
Запуск анимации при появлении Views
(усовершенствование «летящего» счета score). Анимация изменений состояния с помощью TimelineView
( «бонусные очков» для «пирога» Pie
). Анимация View
«переходов» Transition
на экран и с экрана и сдача карт в игре Memorize с помощью модификатора matchedGeometryEffect
.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 9.
Задание на программирование 4.
Код Memorize.
Лекция 10. EmojiArt
Создание приложения для iPad с нуля: Emoji Art. Это возможность заново взглянуть на MVVM, поскольку это приложение имеет совершенно другую архитектуру, чем игра Memorize. Оно использует SwiftUI Drag & Drop механизм для установки фонового изображения документа Emoji Art и добавления эмодзи (смайликов) в произведения искусства, которые вы можете создать с помощью этого приложения.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 10.
Код EmojiArt L10.
Лекция 11. Жесты, вторая MVVM
Обработка мультитач-жестов (масштабирование и перемещение по экрану документов Emoji Art). Начинаем создавать более сложные приложения, добавив в приложение вторую конструкцию MVVM (палитры смайликов Emoji Art).
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 11.
Задание на программирование 5.
Код EmojiArt L11.
Лекция 12. Постоянное хранение (Persistence). Обертки свойства (Property Wrappers)
Обеспечение сохранения информации между запусками приложения. Emoji Art сохраняет свой документ, а также любые изменения, внесенные в его палитры. Файловая система и UserDefaults. Узнаем больше о том, как работают оболочки свойств (например, @State, @Published и т. д.).
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 12.
Код EmojiArt L12.
Лекция 13. Представляющие (Presenting) Views, Navigation
До сих пор каждое из наших двух приложений состояло только из одного основного «СontentView» ( EmojiMemoryGameView
игры Memorize или EmojiArtDocumentView
для приложения Emoji Art). Более сложные приложения должны представлять множество различных видов Views
. Добавление в Emoji Art механизмов редактирования его палитр, представление всплывающих модальных окон .popover
и .sheet
, а также навигация между Views
.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 13.
Задание на программирование 6.
Код EmojiArt L13.
Лекция 14. Многопоточность, Обработка ошибок
UI мобильных приложений должен всегда быть отзывчивым, даже если он должен выполнять действия, которые занимают (относительно) много времени (например, загрузка чего-либо из Интернета). Язык Swift
имеет встроенный механизм, позволяющий прояснить, какие действия должны происходить «в фоновом режиме», чтобы не замедлять работу UI. При этом также важна обработка непредвиденных ошибок, поэтому в этой лекции обе темы представлены вместе.
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 14.
Код EmojiArt L14.
Лекция 15. Документо—ориентированная архитектура
Emoji Art, конечно, хочет поддерживать наличие нескольких документов (как рядом на iPad, так и в нескольких окнах на Mac). SwiftUI
имеет мощный встроенный пользовательский интерфейс для решения этой проблемы, и попутно мы получим поддержку Undo/Redo в Emoji Art!
Смотреть в YouTube.
Русскоязычный иллюстрированный конспект Лекции 15.
Код EmojiArt L15.
Пол Хэгерти очень понятно объясняет ключевую концепцию SwiftUI
- единственный “источник истины” (Single Source Of Truth) через систему обратных “привязок” Binding
из View
через ViewModel
к Model
и внедрения ViewModel
в иерархию Views
через @EnvironmentObject. Это позволяет вам напрямую редактировать данные, хранящиеся в другом месте, из View
любого уровня иерархии и избежать дублирования хранения данных в разных местах.
Но всё это возможно благодаря механизму реактивного UI в SwiftUI
, основу которого составляет протокол ObservableObject
. Правда дважды при разработке приложения Emoji Art Пол Хэгерти выходит на границы возможностей ObservableObject
: при использовании Userdefaults
как вычисляемого свойства с get {}
и set {}
для хранения палитр palettes
заставляет отказаться от явного применения @Published и при использовании массива [ObservableObject]
, который автоматически не является ObservableObject
.
Однако начиная с iOS 17, iPadOS 17, macOS 14, tvOS 17 и watchOS 10, уже после завершения курса CS193P, SwiftUI
предлагает новый фреймворк Observation
, реализующий паттерн наблюдателя, и макрос @Observable против протокола ObservableObject
.
Использование Observation
обеспечивает вашему приложению следующие преимущества:
Отслеживание
Optional
значений и коллекцийCollection
объектов, что невозможно при использованииObservableObject
.Использование существующих примитивов потока данных, таких как @State и @Environment, вместо основанных на объектах эквивалентов, таких как @StateObject и @EnvironmentObject.
Обновление
Views
на основе изменений наблюдаемых свойств, которые считываетbody
конкретныхView
, а не любых изменений свойств, происходящих с наблюдаемым объектом, что может повысить производительность вашего приложения.
Поэтому все объяснения Пола Хэгерти относительно единственного “источника истины” (source of truth) остаются верными с заменой протокола ObservableObject
на макрос @Observable, @StateObject на@State, @EnvironmentObject на @Environment, @ObservableObject
вообще убрать или заменить на@Bindable, все это изложено в “Правилах Миграции от протокола ObservableObject к макросу @Observable”. В русскоязычном конспекте сделаны все необходимые пометки на полях и для всех демонстрационных примеров в GitHub представлена версия с пометкой “Observation”.
Кроме того, наибольшее впечатление производит простое объяснение и реализация многопоточности (async
, await
, Task
) при пользовательской загрузке изображения из Интернета на основе такой абстракции, как конечный автомат, с параллельной обработкой ошибок (throws
, try
, do {} catch {}
).
Отдельного упоминания требует способ хранения DocumentGroup
данных, воспринимаемых пользователями как «документы», а именно таким и является наше приложение Emoji Art. DocumentGroup
способна превратить Emoji Art в многодокументное приложение, которое работает как “родное” приложение в среде Files
как на iOS
, так и на Mac
. Надо сказать, что в интернете не так много информации о полноценном применении DocumentGroup
, так что это просто подарок тем, кто создает приложения, основанные на «документах».
Ссылки:
Оригинальный сайт стэнфордского курса CS193P «Разработка iOS приложения с помощью SwiftUI» семестр Весна 2023 (английский)
“Правилах Миграции от протокола ObservableObject к макросу @Observable”.