Проблема
Чтобы добиться чистого внешнего вида кода приложения, я создаю ViewModels для каждого View, содержащего logi c.
Обычная ViewModel немного похожа на это:
class SomeViewModel: ObservableObject {
@Published var state = 1
// Logic and calls of Business Logic goes here
}
и используется так:
struct SomeView: View {
@ObservedObject var viewModel = SomeViewModel()
var body: some View {
// Code to read and write the State goes here
}
}
Это отлично работает, когда родительский элемент Views не обновляется. Если состояние родителя изменяется, это представление перерисовывается (это нормально для декларативной платформы). Но также воссоздается ViewModel и впоследствии не сохраняет состояние. Это необычно по сравнению с другими фреймворками (например, Flutter).
На мой взгляд, ViewModel должна оставаться, или State должно сохраняться.
Если я замените ViewModel на свойство @State
и используйте int
(в этом примере) напрямую, он остается постоянным, а не воссоздается :
struct SomeView: View {
@State var state = 1
var body: some View {
// Code to read and write the State goes here
}
}
Это явно не работает для более сложных состояний. И если я устанавливаю класс для @State
(например, ViewModel), все больше и больше вещей не работает должным образом.
Question
- Есть ли способ не воссоздавать ViewModel каждый раз?
- Есть ли способ репликации
@State
Propertywrapper для @ObservedObject
? - Почему @State сохраняет состояние при перерисовке?
Я знаю, что обычно создание ViewModel во внутреннем представлении - плохая практика, но это поведение можно воспроизвести с помощью NavigationLink или Sheet.
Иногда тогда просто нецелесообразно сохранять State в ParentsViewModel и работать с привязками, когда вы думаете об очень сложном TableView, где сами ячейки содержат много logi c.
В отдельных случаях всегда есть обходной путь, но я думаю, что было бы намного проще, если бы ViewModel не был воссоздан.
Повторяющийся вопрос
Я знаю, что есть много вопросов, касающихся этой проблемы, и все они говорят об очень конкретных * 1 058 * варианты использования. Здесь я хочу поговорить об общей проблеме, не вдаваясь слишком глубоко в индивидуальные решения.
Edit (добавление более подробного примера)
При наличии ParentView, изменяющего состояние, например, список из База данных, API или кеш (подумайте о чем-нибудь простом). Через NavigationLink
вы можете попасть на страницу сведений, где можно изменить данные. Изменяя данные, реактивный / декларативный шаблон подсказывал нам также обновить ListView, который затем «перерисовал» NavigationLink
, что затем привело бы к воссозданию ViewModel.
Я знаю, что могу сохранить ViewModel в ViewModel ParentView / ParentView, но это неправильный способ сделать это IMO. А поскольку подписки уничтожаются и / или создаются заново - могут быть некоторые побочные эффекты.