Это Лекция 14 курса Stanford CS193p, весна 2021 года.
На этой Лекции профессор подробно, строка за строкой, рассматривает код в главном файле приложения с @main, и очень наглядно демонстрирует, как работает «сцена» Scene. В большинстве случаев вы просто будете использовать одну из двух основных встроенных в SwiftUI “сцен” Scene, которыми являются WindowGroup и DocumentGroup с аргументом newDocument. Есть также DocumentGroup (viewing:) для read-only документов.
WindowGroup и DocumentGroup немного напоминают ForEach для Scenes , но эти ForEach “проходят” не через массив Array “чего-то”. Вместо этого каждая из этих “сцен” Scene создается пользователем либо путем создания «New Window» на Mac, либо путем разделения экрана разными (или одинаковыми) приложениями на iPad. На iPhone создание Scene выполняется только один раз, потому что только одна “сцена” Scene в данный момент находится на iPhone и заполняет собой целый экран.
WindowGroup — это основной не “документо-ориентированный” встроенный в SwiftUI Scene. Это то, что мы использовали до сих пор в обоих наших приложениях Memorize и EmojiArt. Внутри WindowGroup мы просто размещаем топовое View, которое хотим видеть на нашем экране. Мы можем делиться нашей ViewModel в виде @StateObject со всеми “сценами” Scene, которые можно создать.
Эти “сцены” Scene немного отличаются для различных платформ и в вашем приложении может быть множество Scenes. Легче всего это представить на Mac, где каждое “окно” — это маленькая “сцена” Scene, все очень, очень просто. На iPhone тоже легко представить, что такое “сцена” Scene, у вас всего одна “сцена” Scene самого верхнего уровня. Но на iPad вы можете даже не осознавать, что там происходит со “сценами» Scenes.
Поэтому профессор не торопится переходить сразу к DocumentGroup. Сначала он дает нам почувствовать в полной мере, что такое «сцена» Scene, оставаясь в пределах WindowGroup и рассматривая попутно такие «Обертки Свойства», как @SceneStorage, @AppStorage и @ScaledMetric. Все это сопровождается великолепным демонстрационным примером на iPad. В результате чего мы приходим к тому, что если мы оставим наше приложение EmojiArt в WindowGroup, то всё, на что можно рассчитывать — это автосохранение единственного документа.
Это приводит нас прямо к разговору об архитектуре “документо-ориентированного” приложения в SwiftUI, в котором главным действующим лицом является “документ” наподобие EmojiArt. Конечно, мы хотим, чтобы у каждого документа EmojiArt была своя собственная ViewModel и чтобы каждый документ имел свой отдельный файл. Но кроме этого мы хотим иметь возможность переименовывать, перемещать эти файлы, удалять эти файлы и т.д. и все это в одном приложении.
У SwiftUI есть очень мощный механизм, который заботится обо всем этом вместо нас, и на Лекции 14 профессор учит нас использовать этот механизм, который называется DocumentGroup. Он превращает EmojiArt в многодокументное приложение и позволяет ему работать как “родному” приложению как на iOS, так и на Mac. Для этого не требуется много кода.
Фактически, чтобы заставить вашу ViewModel, какой бы она ни была, работать с механизмом DocumentGroup, она должна соответствовать протоколу с именем ReferenceFileDocument, довольно простому протоколу, он заботится о том, как разместить наш документ на диске, и как его восстановить с диска.
Другая вещь, касающаяся ReferenceFileDocument подхода к нашей ViewModel, состоит в том, что она должна, по существу, реализовать функцию отмены Undo изменений документа, которую мы, конечно же, рады иметь в любом случае. Потому что отмена Undo — это способ, с помощью которого “документо-ориентированная” архитектура DocumentGroup узнаёт о том, что ваш документ изменен, и может его автоматически сохранить.
В своем демонстрационном примере профессор очень подробно проходит все логические этапы превращения нашего EmojiArt приложения WindowGroup в многодокументное приложение DocumentGroup, начиная от создания Универсального Идентификатора Типа UTType для наших EmojiArt документов и кончая UndoManager и кодом для регистрации операций как Undo операций. В некотором смысле это пазл, который нужно ПРАВИЛЬНО сложить из отдельных не очень сложных кусочков. И профессор Пол Хэгерти очень четко показывает нам, как можно это сделать.
Я нигде не видела в «сети», чтобы процесс создания многодокументного DocumentGroup приложения был представлен полностью с логическим обоснованием того, что за чем делаем и почему. Обычно присутствуют только какие-то обрывки этой процедуры.
Код демонстрационного примера для Лекции 14 находится на Github для iOS 14 в папке EmojiArtL14.
Русскоязычный неавторизованный конспект Лекции 14, иллюстрированный, хронометрированный и представленный в виде PDF-файла, который можно скачать и использовать offline, а также в формате Google Doc доступны на платной основе.