Ниже представлен небольшой фрагмент Лекции 14 Стэнфордского курса CS193P Весна 2023 «Разработка iOS приложений с помощью SwiftUI«.
Полный русскоязычный неавторизованный конспект Лекции 14 в формате Google Doc и в виде PDF-файла, который можно скачать и использовать offline, доступны здесь.
Код находится на GitHub.
С полным перечнем Лекций и Домашних Заданий на русском языке можно познакомиться здесь.
. . . . . . . . . . . . . .
Демонстрационный пример: конечный автомат Background
Итак, давайте поговорим о том, как я собираюсь загружать фоновое изображение background концептуально. Я собираюсь использовать конечный автомат (state machine
).
Сколько человек реально написали код, который использует конечный автомат (state machine
)?
Ну, не так уж и много. Интересно.
Итак идея программирования конечных автоматов заключается в том, что я собираюсь подумать обо всех состояниях (states
), в которых я могу оказаться, и выполняю некоторый процесс. На самом деле я собираюсь закодировать их и делать каким-то образом пометки в моем коде для каждого из этих шагов. И отличный ТИП данных для конечных автоматов — это перечисление enum. Потому что по определению вы перемещаетесь по этим различимым состояниях (states
), a перечисление enum как раз и представляет различимые состояния (states
).
Вот что представляет собой мой конечный автомат (state machine
). Я размещу весь этот код отдельно, в разделе // MARK: — Background Image. Это будет перечисление enum с именем Background:
И каковы состояния (states
) выборки чего-либо из Интернета?
Вы можете быть в состоянии none, то есть вы ничего не делаете. Нет, фонового изображения background, которое Drag & Drop (перетаскивается и сбрасывается), вы просто нигде:
Возможно, я сейчас выбираю данные из Интернета, так что я мог бы назвать состояние fetching. Но когда я выбираю, возможно, я хочу знать URL, по которому идет выборка, и я могу получить URL в качестве ассоциированных данных:
Итак, я сделал выборку по этому URL, и либо у меня есть изображение, либо мне не удается этого сделать из-за какого-то сетевого сбоя или чего-то в этом роде.
В результате у меня действительно добавляются еще два состояния в моем конечном автомате.
В случае успешного завершения выборки я нахожусь в состоянии found с изображением UIImage, в противном случае я нахожусь в состоянии failed, и в этом случае я мог бы сохранить ошибку, которую я получил:
Для простоты я сохраняю ошибку в виде String, которая описывает, вероятно, localizedDescription полученной ошибки.
Итак, это состояния моего конечного автомата.
Я собираюсь пройти через эти состояния шаг за шагом и выполнить все необходимые действия.
Теперь, поскольку у меня есть этот маленький конечный автомат enum Background, я также создал небольшие удобные функции.
Давайте посмотрим на них:
Это маленькие переменные var, которые просто возвращают ассоциированные данные определенного состояния моего конечный автомат enum Background, если я нахожусь в этом состоянии.
Итак, вы видите вычисляемую переменную var uiImage:
Внутри мы переключаемся switch по self, и если я нахожусь в состоянии found с ассоциированным значение uiImage в виде выбранного изображения, то возвращает это изображение uiImage. В противном случае он просто возвращает nil.
То же самое происходит с получением URL-адреса urlBeingFetched, по которому осуществляется выборка:
Внутри мы переключаемся switch по self, и если я нахожусь в состоянии fetching с ассоциированным значение url, то возвращает этот url, по которому идет выборка изображения. В противном случае он просто возвращает nil.
То же самое с причиной неудачной выборки failureReason:
Если я нахожусь в состоянии failed, дайте мне причину reason моей неудачи.
Это всего лишь удобные переменные.
Так что я могу просто спросить, какое у меня фоновое изображение uiImage прямо сейчас?
И это будет nil, если у меня его просто нет. Если я не в состоянии found, когда я получаю изображение uiImage, a в любом другом состоянии: none или fetching или failed, я также получу nil.
Я разместил также маленькую Bool переменную var isFetching:
Эта переменная равна true только в том случае, когда мой urlBeingFetched не равен nil, то есть когда я действительно выбираю изображение из Интернета. Потому что когда я нахожусь; в состоянии fetching, у меня есть URL-адрес, и это единственное состояние, когда у меня есть этот URL-адрес.
Теперь, когда у меня есть мой компактный конечный автомат enum Background, я собираюсь избавиться от переменной var background, я закомментирую это, чтобы запомнить, как это было:
Вместо этого я собираюсь создать новую @Published переменную var, которую назову background, её ТИП будет Background и её начальное значение будет .none:
Я делаю её @Published, потому что именно так мой UI будет видеть фоновое изображение background. UI всегда имеет возможность увидеть, в каком состоянии я нахожусь, потому что смотрите — я даю ему это перечисление enum Background, в котором вы также можете использовать удобные функции.
Читать далее