Лекция 5. Протоколы, перечисления enum, Optional. CS193P Spring 2023.

Ниже представлен фрагмент Лекции 5 Стэнфордского курса CS193P Весна 2023 «Разработка iOS приложений с помощью SwiftUI«.
Полный русскоязычный неавторизованный конспект Лекции 5 в формате Google Doc и в виде PDF-файла, который можно скачать и использовать offline, доступны здесь.
Код находится на GitHub.

С полным перечнем Лекций и Домашних Заданий на русском языке можно познакомиться здесь.

. . . . . . . . . . . . . .

Анимация карт cards

Я сказал вам, что не собираюсь показывать вам анимацию на этой неделе. Я не собираюсь показывать вам это и на следующей неделе, даже после того, как мы потратим всю неделю на изучение анимации. Об анимации нам предстоит многое узнать. Анимация очень важна в мобильных приложениях на iPad или iPhone, и очень важно иметь хорошую анимацию.
Но сегодня
я собираюсь показать вам самую примитивную анимацию, потому что она поведет нас по пути реализации протоколов protocol, соответствия протоколам, превращения наших “не важно каких” (don’t care) Generic ТИПов в “немного важно какие” Generic ТИПы с ограничениями и все такое.

Я добавлю немного анимации к нашим картам cards.
Вот наши карты cards на UI. Вы видите, что здесь есть ScrollView, VStack — это наши карты cards, которые представляют собой сетку LazyVGrid:

Я хочу применить анимацию к моим картам cards, и собираюсь использовать значение по умолчанию .default для вида анимации. Это только один из возможных видов анимации, которую мы можем задать с помощью этого View модификатора. Мы поговорим обо всех других видах анимации позже.

Видите этот ViewModifier? Он меняет этот View, чтобы наделить его анимацией.
Здесь есть аргумент value. Какое значение мы должны ему дать? Все что угодно, любую переменную var, которую вы хотите, и анимация будет происходить только, если внутри этого View значение value изменится. Мы действительно должны указать то, что может вызвать анимацию наших карт cards, и это viewModel.cards:

По сути, когда любая из наших карт изменится, нам нужно её анимировать.
Вот почему я размещаю здесь viewModel.cards в качестве value. Итак, если наш viewModel.cards изменится, то любое из этих изменений вызовет анимацию. Например, когда я кликну на кнопке Shuffle (Перетасовать),  то произойдет анимация перетасовки карт.

Протокол Equatable

Читать далее

Лекция 4. Применение MVVM. CS193P Spring 2023.

Ниже представлен фрагмент Лекции 4 Стэнфордского курса CS193P Весна 2023 «Разработка iOS приложений с помощью SwiftUI«( с замечаниями на полях относительно изменений в iOS 17 — фреймворк Observation).
Полный русскоязычный неавторизованный конспект Лекции 4 в формате Google Doc и в виде PDF-файла, который можно скачать и использовать offline, доступны здесь.
Код находится на GitHub.

С полным перечнем Лекций и Домашних Заданий на русском языке можно познакомиться здесь.

Итак, вся эта неделя будет посвящена этой картинке, которую я показал вам на прошлой Лекции.

Она относится к нашей игре Memorize таким образом, что мы собираемся использовать её для построения ЛОГИКИ игры, а к концу Среды мы уже на самом деле будет играть в игру Memorize.
Давайте просто вернемся к нашему коду, к тому места, на котором мы остановились в прошлый раз.

Позвольте мне дать некоторый обзор того, где мы находимся на данный момент, по сравнению с представленной выше картинкой. То, что вы видите здесь, этот класс class : EmojiMemoryGame, наша ViewModel. На первой и нашей основной картинке это зеленая вещь:


А это наша Model (Модель). На первой картинке это синяя штука внизу.

В настоящее время мы уже создали наше View, оно называется ContentView:

Мы собираемся изменить его на что-то другое, но кусочек его мы уже создали. Обратите также внимание, что когда я кликнул на файле MemorizeGame, то увидел, что там находится структура struct с именем MemoryGame. Давайте просто переименуем файл, вам разрешено выделять имена файлов и …

… изменять их:

Если вы хотите переименовать актуальную структуру struct, тогда вам нужно переименовывать немного больше вещей, поскольку вы даете новое имя структуре struct, файлу и другим вещам, ссылающимся на эту структуру struct. На самом деле я собираюсь показать вам, как это сделать, когда мы будем переименовывать структуру struct ContentView в EmojiMemoryGameView, это имя значительно лучше слишком обобщенного имени ContentView. Я покажу вам это через секунду. Если вы вернетесь в ваш ViewModel, вы заметите, что там мы создали переменную var для нашей модели model:

На первой и основной картинке наш ViewModel имеет полную возможность подключения к Model (Модели). Он может «поговорить» с Model (Моделью) обо всём, что ему нужно, потому что вся его работа именно в этом и состоит: чтобы понять Model (Модель), «поговорить» с ней, интерпретировать её данные и представить их View действительно наилучшим способом. 

Иногда мне нравится называть ViewModel “дворецким” (butler) Views. Вы когда-нибудь смотрели «Аббатство Даунтон» или что-то подобное? Там вы видите этих старых “дворецких”, они накрывают на стол, чтобы вы вкусно пообедали, и они устраивают все ваши дела. Именно это и делает ViewModel, беря все, что есть в Model (Модели), и организуя это наилучшим образом, чтобы у View был такой красивый и простой код, что всё действительно понятно.
В этом и состоит роль ViewModel
Конечно, у ViewModel  есть переменная var model прямо в коде:

Читать далее

Лекция 2. Ещё больше SwiftUI. CS193P Spring 2023.

Ниже представлен начальный фрагмент Лекции 2 Стэнфордского курса CS193P Весна 2023 «Разработка iOS приложений с помощью SwiftUI«.
Целиком конспект Лекции 2 можно прочитать на Google Doc здесь.
Код находится на GitHub.

С полным перечнем Лекций и Домашних Заданий на русском языке можно познакомиться здесь.

Иногда мне нравится начинать свои Лекции с возврата на предыдущую лекцию и доделывать всё, что забыл там сделать. Вы видели, как проходят Лекции —  мне нужно слишком многое вам рассказать. и иногда я слишком быстро что-то проскакиваю.

Режим Выбора (Selection)  в Preview


Итак, я хотел бы начать с возвращения к предыдущей Лекции и немного уточнить одну вещь, связанную с инспектором.
 

Помните, я говорил вам, что вы можете войти в режим Выбора (Selection) внизу вашего PreView.
В режиме Выбора (Selection) вы сможете выбирать элементы вашего UI или даже несколько элементов одновременно.

Пару замечаний об этом. Я говорил о том, почему это важно, ведь если вы умеете программировать, зачем вам это нужно? И я приводил примеры,  кому это нужно: локализаторам или дизайнерам вашего UI, которые могут и не быть программистами. 
Однако не значит, что это не имеет абсолютно никакой важности лично для вас. Это может быть хорошо для настройки определенных элементов UI.

И еще одна вещь, которую следует отметить по этому поводу. Я не думаю, что я упомянул о том, что этот режим Выбора (Selection) работает в обе стороны. Если я кликну на  строка кода, то будет выбраны (голубой рамкой) элементы UI, представляющие этот код:

И наоборот, если вы выберите элемент UI, то будет подсвечен код, представляющий этот элемент UI. Другими словами, дело не только в том, что ВЫ выбираете, а что выбирает XCode. Если вы выберете любой из двух вариантов, то будет выбран другой, поэтому я хочу, чтобы вы это поняли. 
И тогда как программисту, почему бы вам не повозиться с цвет или с некоторыми отступами или с чем-то еще в этом роде без необходимости постоянно печатать и редактировать исходный код. Это зависит от того, что вам нравится. Лично я люблю редактировать исходный код. Это как бы вытекает из моего мироощущения, поэтому мне нравится все делать в коде. Но некоторым людям нравится кликать на кнопки. И поэтому я просто не хотел принижать возможности Инспектора и режима Выбора (Selection). Это может быть интересным и значимым.
Итак, это было единственное, к чему из прошлой Лекции я хотел вернуться .

Настройки проекта  Project Settings 

Еще одна вещь, которую я хотел бы упомянуть.  Когда мы вышли на Навигатор в раздел Файлы, я сказал: “Посмотрите, есть три файла: MemorizeApp, ContentView и Assets. Но на самом деле есть еще одна вещь,  вы можете кликнуть на самой верхней строке иерархии, это что-то вроде файла, и увидеть настройки Project Settings вашего проекта. 

Читать далее

Лекция 1. Начало работы со SwiftUI. CS193P Spring 2023.

Ниже представлен начальный фрагмент Лекции 1 Стэнфордского курса CS193P Весна 2023 «Разработка iOS приложений с помощью SwiftUI«. Целиком конспект Лекции 1 можно прочитать на Google Doc здесь. Код находится на GitHub.

С полным перечнем Лекций и Домашних Заданий на русском языке можно познакомиться здесь.

Введение

Привет, Интернет, и добро пожаловать на курс CS193P Стэнфордского университета Весна 2023: Разработка приложений для iOS с использованием SwiftUI.

Я —  Пол Хегарти. Я веду этот курс уже 13 или 14 лет, и время от времени я записываю его и выкладываю в Интернет на всеобщее обозрение, чтобы вы могли видеть, чем мы занимаемся здесь, в Стэнфорде.

К сожалению, в этом семестре я этого не сделал. Мы вернулись в кампус после пандемии и я не установил все необходимые камеры для этого, так что прошу прощение за это. Тем не менее, я записал скриншоты экрана своего ноутбука. Мне пришлось это сделать, потому что моим студентам при выполнении Домашних Заданий 1 и 2 необходимо следить за тем, что я делаю, иногда им нужно иметь возможность вернуться назад и увидеть код демо-версии. Это хорошо и для вас, потому что вы можете делать то же самое. Это также очень хорошо для моих основных слайдов, где я рассматриваю некоторые концепции SwiftUI и т. д. А еще я весь семестр держал в ухе этот AirPod, так что, надеюсь, звук во всем этом будет довольно хорошим.

Однако есть вещи, которые вы не увидите на экране. Например, для карточной игры, которую мы разрабатываем на этом курсе, я сделал несколько настоящих карточек. 

Я также довольно часто использую LEGO (Лего) в качестве аналогии SwiftUI. Вы не сможете увидеть мой вертолет LEGO и мою печально известную сумку LEGO … 

… но обязательно услышите о них, когда будете слушать демонстрационные примеры.

А еще у нас есть совершенно замечательный большой проекционный экран, и я обычно ходил перед ним и жестикулировал при написании кода. Очевидно, вы не увидите на видео моих жестов. Надеюсь, что шрифты будут достаточно большими, чтобы вы могли их увидеть на небольшом устройстве, но если нет, то вам, возможно, придется перейти на iPad или что-то в этом духе. Но я думаю, что в целом все будет очень хорошо.

Итак, это университетский курс. Лекции курса CS193P Spring 2023 читаются каждую неделю в течение 10 недель. Мы пытаемся понять не только то, как разработать приложение для iOS, но и то, как работает система SwiftUI в целом?

Читать далее

Лекция 16. Мультиплатформенная версия EmojiArt (macOS). CS193P Весна 2021г.

Это Лекция 16 курса Stanford CS193p, весна 2021 года.

Эта лекция полностью посвящена мультиплатформенной поддержке. В частности, запускается приложение EmojiArt на Mac как собственное приложение для macOS, но при этом вы будете удивлены парой вещей. Одна из них — это какой мощный UI мы создали для работы с документами на Mac на базе документо-ориентированной SwiftUI архитектуры, а также сколько нашего iOS кода практически без модификации работает на Mac. Для той части, которая не работает, применяется несколько стратегических хитростей, способных максимально адаптировать наш код к мультиплатформенности.

На Лекции 16 профессор создает единый проект с большим количеством общего кода, и да,  с некоторыми #if os(…) — else #endif, потому что две платформы, macOS и iOS, это не одно и то же. У них не совсем один и тот же способ взаимодействия с пользователями и т. д., так что он адаптирует код к разным платформам.

Читать далее

Лекция 15. Интеграция с UIKit. CS193P Весна 2021г.

Это Лекция 15 курса Stanford CS193p, весна 2021 года.

Хотя название Лекции «Интеграции с UIKit«, задача этой Лекции — более широкая, заставить работать наше документо-ориентированное приложение EmojiArt на iPhone. До сих пор функциональные возможности приложения EmojiArt в большей степени были ориентированы на iPad. Запуск этого приложения на iPhone показал, что большая часть кода прекрасно адаптируется самой SwiftUI, например, popover на iPad автоматически преобразуется в полноэкранный sheet на iPhone, но не все работает так гладко.

Например, нам пришлось добавить ещё три способа получения фонового изображения background для нашего документа, ибо перетягивание его из Safari, находящегося тут же на экране iPad, в случае iPhone не работает.

Вот эти способы :

  • копирование  и вставка (Copy & Paste) изображения c  Pasteboard
  •  изображение с фотокамеры
  •  изображение из Библиотеки Фотографий (Photo Library)

Для этого мы должны были решить вопрос размещения множества кнопок Button, соответствующих различным способам получения фонового изображения документа, на панели инструментов toolbar, а также вопросы интеграции UIKit API  фотокамеры и Библиотеки Фотографий (Photo Library) в SwiftUI приложение.

Читать далее

Лекция 14. «Документо-ориентированная» архитектура. CS193P Весна 2021г.

Это Лекция 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. Для этого не требуется много кода. 

Читать далее

Лекция 13. «Издатель» Publisher. Ещё о «постоянном хранении». Cs193P Весна 2021г.

Это Лекция 13 курса Stanford CS193p, весна 2021 года.

Лекция 13 посвящена 3-м темам:

  • “издатель” Publisher
  •  “постоянное хранения” (persistence) в «облаке» CloudKit
  • “постоянное хранение” (persistence) в локальной базе данных CoreData.

Две бонусные лекции (Enroute) с демонстрацией CoreData были прочитаны весной 2020 года, а не весной 2021 года. Изложенный материал (Picker, использование Codable для извлечения данных из REST API и CoreData) по-прежнему актуален (по крайней мере, на весну 2021 года), поэтому эти лекции также включены сюда. Ссылки представлены в конце этого поста.

“Издатель” Publisher

Первая тема — это “издатели” Publisher, своего рода API, некоторый формализм, для потоковой информации, которая порождается одной частью вашей программы, a потребляется — другой.

“Издатель” Publisher — это лишь один из «игроков» реактивного Swift фреймворка Combine, который оперирует такими абстрактными понятиями, как «издатели» Publishers, «подписчики» Subscribers и операторы Operators. Благодаря тому, что Apple предоставляет разработчикам уже готовых «издателей», «подписчиков» и операторов, код, написанный с помощью Combine, оказывается очень компактным и хорошо читаемым.

Читать далее

Лекция 12. Привязка Binding. «Всплывающие окна» sheet popover Alert. Navigation. EditMode. CS193P Spring 2021.

Это Лекция 12 курса Stanford CS193p, весна 2021 года.

На этой фантастической и очень важной Лекции (она длится почти 2 часа) Пол Хэгерти рассматривает супер важную тему — Property Wrappers (“Обертки Свойства”). Мы наконец-то поймем, что такие вещи как @State, @StateObject, @Published, @ObservedObject и другие @штуковины делают под «капотом». Поэтому сначала эту тему профессор представляет теоретически, то есть на слайдах, а затем следует громадная демонстрация, на которой показывается все это в действии, но не только это, а также много всего другого, что можно изучить только в  демонстрационном пример: текстовые поля TextField, «всплывающие окна» popover и sheet, навигацию с помощью NavigationView, формы Form, списки List, режим редактирования EditMode и т.д, интересные модификаторы .onDelete, .onMove, .onChange.

Property Wrapper (“Обертка Свойства”) — это просто структура struct, в которую встроен некоторый шаблон “поведения”переменной var, которую эта структура struct “оборачивает”.

Например, @State заставляет переменную var “жить” в “куче” (heap), делая её writable в View, то есть дает возможность “писать” в нее новые значения в противоположность обычным переменным var в View, которые являются unwritable (только для чтения).

Мы знаем, что @Published публикует изменения переменной var, которые заставляют Views перерисовывать себя или делать другие подобные вещи.

То же самое происходит с @ObservedObject переменной var, которая отслеживает изменения в вашей ViewModel и заставляет View перерисовывать себя.

Читать далее

Лекция 11. Постоянное хранение (Persistence). Обработка ошибок. CS193P Spring 2021.

Это Лекция 11 курса Stanford CS193p, весна 2021 года.

Главная тема этой Лекции — «постоянное хранение» (Persistence), то есть хранение данных в файловой системе и других местах на самом устройстве и в iCloud. Теме «постоянного хранения» сопутствуют еще две важные темы. Это формат хранения данных (самым распространенным форматом является JSON формат) и обработка ошибок, ибо операции ввода/ вывода типа записи на диск или считывания с диска, сопутствующие «постоянному хранению» (Persistence), порождают достаточное количество возможных фатальных ошибок, требующих обработки. Что касается JSON формата, то в Swift существует очень мощный Codable механизм, который позволяет практически любую структуру struct или перечисление enum превратить в  Blob данных в формате JSON.

Все 3 темы — «постоянное хранение» (Persistence), обработка ошибок  и механизм Codable — сначала рассматриваются теоретически, а затем и в демонстрационном примере. Читать далее