Connect with us

Разработка

Шаблоны проектирования для SwiftUI

Давайте рассмотрим некоторые паттерны, которые можно применить в SwiftUI.

Опубликовано

/

     
     

Шаблоны проектирования путают умы людей, работающих со SwiftUI. Они задаются такими вопросами, как «Какой паттерн больше подходит для SwiftUI?» или «Нужно ли вообще использовать шаблон?». Apple также предоставила некоторую информацию об использовании паттернов для SwiftUI на WWDC. Давайте рассмотрим некоторые паттерны, которые можно применить в SwiftUI.

1. MVVM (Model-View-ViewModel)

В MVVM нам нужно обратить внимание на то, чтобы правильно применить логику наблюдаемости, так как в шаблоне есть другой слой представления по сравнению с проектом Swift. Пример класса представления вы можете увидеть ниже.

Экземпляр SearchViewModel определен как ObservedObject, поэтому при изменении модели представления UI будет перезагружен, и мы сможем увидеть соответствующие изменения. Еще одним важным моментом здесь является то, что класс ViewModel соответствует протоколу ObservableObject.

Мы можем использовать несколько специальных макросов для переменных класса ViewModel, к которым мы хотим применить изменения. Одним из них является макрос @Published. Мы определили переменную results в классе SearchViewModel как Published. Каждый раз, когда переменная results будет обновляться, соответствующее представление будет перезагружаться.

2. Координатор

Координатор выделяется тем, что предлагает более упрощенную структуру навигационных переходов между представлениями. Другими словами, он позволяет нам взять навигационные операции из представления и использовать их в более управляемой и многократно используемой структуре. Возможно, вы уже слышали о MVVM+C, поэтому мы можем использовать координатор для навигационных операций с MVVM.

Допустим, в проекте есть представление login. Давайте создадим структуру Output, которая позволит нам перенести навигационные операции из слоя представления. Для этого примера предположим, что из LoginView мы можем перенаправлять на главный экран и экран ForgotPasswordView, поэтому мы создали два метода внутри структуры Output.

Мы можем осуществлять переход к соответствующим экранам через экземпляр output, как в примере в body ниже.

Итак, теперь давайте рассмотрим, как мы можем инициировать экземпляр output в классе координатора.

Предположим, что у нас есть класс координатора для каждого модуля и главный класс координатора, из которого мы можем управлять всеми классами координаторов. Для этого примера создадим класс AuthenticationCoordinator для управления операциями навигации в модуле login и класс AppCoordinator для управления всеми координаторами.

Создадим наблюдаемый экземпляр AppCoordinator в главной структуре приложения. Выполним маршрутизацию через NavigationStack и определим путь NavigationStack как appCoordinator.path, а rootView NavigationStack как appCoordinator.view().

Для .navigationDestination, если он имеет тип AuthenticationCoordinator, мы вызываем метод view() соответствующего координатора.

Теперь давайте посмотрим на rootView из NavigationStack, который является методом view() координатора AppCoordinator.

Мы инициализировали MainView в view методе AppCoordinator. В MainView мы перешли к AuthenticationCoordinator.

В класс AuthenticationCoordinator мы инжектировали страницу, на которую хотим перейти, navigationPath и output. В классе координатора у нас также есть структура Output, потому что у него также есть вывод, например, переход на главный экран после завершения операций входа в систему.

После создания AuthenticationCoordinator в MainView мы вызвали метод view(), который я напишу ниже. С помощью этого метода мы создаем экземпляр соответствующего экрана (login или forgotPassword). Таким образом, мы инициируем соответствующее представление.

3. Clean Swift (VIP)

В Clean Swift мы выполняем все операции обновления представления с помощью наблюдения. Мы можем начать применять шаблон, создав шаблон VIP. В этом примере есть 4 различных слоя (Worker-Presenter-Interactor-View). В ContentView мы вызываем метод builder, который позволяет нам инициализировать экземпляры слоев.

Мы определяем переменную interactor в слое представления, чтобы запустить use-cases. Также мы инициализируем наблюдаемую displayModel, чтобы быть в курсе обновлений в viewModel и применять их к представлению.

Мы вызвали метод interactor.loadChocolate в .onAppear, так что VIP-цикл начался.

Давайте посмотрим на класс interactor. Вместо реального вызова API мы извлекаем данные из JSON, создаем ответ и форвардим его презентеру.

В презентере мы создаем viewModel с соответствующей ей моделью displayModel и отправляем ее на слой представления через метод показа.

Мы обновляем обозреваемую переменную экземпляра displayModel в методе display, чтобы соответствующее представление было обновлено новыми данными.

4. MV (Model-View)

Этот паттерн, который Apple представила на конференции WWDC, основан на логике «View is the ViewModel». Все бизнес-операции мы выполняем в классе модели. Пример вы можете увидеть ниже.

В классе представления выполняются все операции над представлением и, кроме того, все операции над ViewModel.

Вот и все. Не забудьте поделиться с коллегами статьей.

Источник

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: