Я пытаюсь создать объект EnvironmentObject, к которому может обращаться модель представления (а не только представление).
Объект Environment отслеживает данные сеанса приложения, например, loggedIn, токен доступа и т. Д., Эти данные будут передаваться в модели представлений (или, при необходимости, классы обслуживания), чтобы позволить вызову API для передачи данных из этого EnvironmentObjects.
Я попытался передать объект сеанса инициализатору класса модели представления из представления, но получил ошибку.
Как я могу получить доступ / передать EnvironmentObject в модель представления с помощью SwiftUI?
Смотрите ссылку на тестовый проект: https://gofile.io/?c=vgHLVx
Ответы:
Я предпочитаю не иметь ViewModel. (Может быть, время для нового образца?)
Я настроил свой проект с
RootView
несколькими дочерними представлениями. Я насторитьRootView
сApp
объектом как EnvironmentObject. Вместо того, чтобы ViewModel обращался к моделям, все мои представления обращаются к классам в App. Вместо ViewModel, определяющего макет, иерархия представления определяет макет. Сделав это на практике для нескольких приложений, я обнаружил, что мои взгляды остаются небольшими и конкретными. В качестве упрощения:В моих предварительных просмотрах я инициализирую a,
MockApp
который является подклассомApp
. MockApp инициализирует назначенные инициализаторы с объектом Mocked. Здесь UserService не нужно подвергать насмешке, но источник данных (то есть NetworkManagerProtocol) делает это.источник
app.userService.logout()
.userService
должен быть закрытым и доступным только из класса приложения. Приведенный выше код должен выглядеть следующим образом:Button(action: { app.logout() })
и функция выхода из системы будет вызываться напрямуюuserService.logout()
.Ты не должен. Это распространенное заблуждение, что SwiftUI лучше всего работает с MVVM.
MVVM нет места в SwfitUI. Вы спрашиваете, можете ли вы вставить прямоугольник в
соответствовать форме треугольника. Это не подходит.
Давайте начнем с некоторых фактов и будем работать шаг за шагом:
ViewModel является моделью в MVVM.
MVVM не принимает во внимание тип значения (например, такого нет в Java).
Модель типа значения (модель без состояния) считается более безопасной, чем эталонная
Типовая модель (модель с состоянием) в смысле неизменности.
Теперь MVVM требует от вас настроить модель таким образом, чтобы при каждом ее изменении она
обновляет вид некоторым заранее определенным способом. Это известно как связывание.
Без привязки у вас не будет хорошего разделения проблем, например; рефакторинг
модель и связанные с ней состояния и отделение их от вида.
Это две вещи, которые большинство разработчиков iOS MVVM терпят неудачу:
В iOS нет «связующего» механизма в традиционном Java-смысле.
Некоторые просто игнорируют привязку и думают, что вызывают объект ViewModel.
автоматически все решает; некоторые введут Rx на основе KVO, и
усложнить все, когда MVVM должен сделать вещи проще.
модель с состоянием просто слишком опасна
потому что MVVM уделяет слишком много внимания ViewModel, слишком мало - управлению состоянием
и общие дисциплины в управлении контролем; большинство разработчиков в конечном итоге
думая модель с состоянием, которое используется для обновления представления, можно использовать повторно и
проверяемый .
Вот почему Swift представляет тип значения в первую очередь; модель без
штат.
Теперь к вашему вопросу: вы спрашиваете, может ли ваш ViewModel иметь доступ к EnvironmentObject (EO)?
Ты не должен. Потому что в SwiftUI модель, соответствующая View, автоматически имеет
ссылка на ЭО. Например;
Я надеюсь, что люди могут оценить, как компактный SDK разработан.
В SwiftUI MVVM работает автоматически . Нет необходимости в отдельном объекте ViewModel
это вручную связывает с просмотром, который требует ссылки EO, переданной ему.
Приведенный выше код является MVVM. Например; модель с привязкой к виду.
Но поскольку модель является типом значения, то вместо рефакторинга модели и состояния
Для просмотра модели вы реорганизуете управление (например, в расширении протокола).
Это официальный SDK, адаптирующий шаблон дизайна к языковой функции, а не просто
навязывая это. Приоритет содержания над формой.
Посмотрите на ваше решение, вы должны использовать синглтон, который в основном глобальный. Вы
должен знать, насколько опасно получать доступ к глобальным ресурсам без защиты
неизменность, которой у вас нет, потому что вы должны использовать модель ссылочного типа!
TL; DR
Вы не делаете MVVM Java-способом в SwiftUI. И Свифт-й способ сделать это не нужно
чтобы сделать это, это уже встроено.
Надеюсь, что больше разработчиков увидят это, так как это кажется популярным вопросом.
источник
Ниже представлен подход, который работает для меня. Протестировано со многими решениями, начатыми с Xcode 11.1.
Проблема возникла из-за того, что EnvironmentObject вводится в общую схему.
то есть в первом созданном виде, во втором созданном объекте среды, в третьем объекте среды, введенном в вид
Таким образом, если мне нужно создать / настроить модель представления в конструкторе представления, то объекта среды там еще нет.
Решение: разбить все на части и использовать явное внедрение зависимостей
Вот как это выглядит в коде (общая схема)
Здесь нет никакого компромисса, потому что ViewModel и EnvironmentObject по своему дизайну являются ссылочными типами (на самом деле
ObservableObject
), поэтому я передаю здесь и там только ссылки (так называемые указатели).источник