SwiftUI - ObservableObject создается несколько раз
Я создал ObservableObject в представлении.
@ObservedObject var selectionModel = FilterSelectionModel()
Я поставил точку останова внутри FilterSelectionModel
с init
функция и вызывается несколько раз. Поскольку это представление является частьюNavigationLink
, Я понимаю, что он создается тогда и вместе с ним selectionModel. Когда я перехожу к представлению, selectionModel создается снова.
В этом же представлении у меня есть "вспомогательное представление", в котором я передаю selectionModel как EnvironmentObject
так что подвид может изменить это.
AddFilterScreen().environmentObject(self.selectionModel)
Когда подвид закрывается, selectionModel создается еще раз, и внесенные в него изменения исчезают.
Интересное примечание: на самом верхнем уровне находитсяNavigationView
. ЕСЛИ я добавлю
.navigationViewStyle(StackNavigationViewStyle())
к этому NavigationView
, мои изменения selectionModel исчезают. НО если я не добавлюnavigationStyle
, изменения selectionModel, сделанные во вспомогательном представлении, остаются!! (Но мне не нужен разделенный вид навигации, мне нужен составной вид навигации)
В обоих случаях - с или без navigationStyle
, selectionModel создается несколько раз. Я не могу понять, как все это должно работать надежно.
2 ответа
Последние обновления SwiftUI принесли решение этой проблемы. (iOS 14 и более поздние версии)
это то, что мы должны использовать вместо , но только там, где этот объект создается, а не везде в подвидах, где мы передаем один и тот же объект.
Например-
class User: ObservableObject {
var name = "mohit"
}
struct ContentView: View {
@StateObject var user = User()
var body: some View {
VStack {
Text("name: \(user.name)")
NameCount(user: self.user)
}
}
}
struct NameCount: View {
@ObservedObject var user
var body: some View {
Text("count: \(user.name.count)")
}
}
В приведенном выше примере только представление, ответственное ( ContentView ) за создание этого объекта, аннотирует объект с помощью
@StateObject
и все другие представления ( NameCount ), которые совместно используют объект.
@ObservedObject
.
При таком подходе всякий раз, когда ваше родительское представление ( ContentView ) воссоздается, объект не будет воссоздан, и он сохранит свое @State , в то время как ваши дочерние представления просто
observing
к тому же
User
объект не должен заботиться о своем воссоздании.
Вы можете создать экземпляр наблюдаемого объекта в методе init, таким образом вы сможете сохранить его значение, иначе значение не исчезнет.
Создайте экземпляр этого способа в файле представления.
@ObservedObject var selectionModel : FilterSelectionModel
init() {
selectionModel = FilterSelectionModel(value : "value to be saved from disappearing")
}
Создайте экземпляр этого способа в файле viewModel.
class FilterSelectionModel : ObservableObject {
@Published var value : String
init(value : String) {
self.value = value
}
}
Это обходной путь, который я нашел, но все же метод init вызывается несколько раз, и я не добился успеха с этой проблемой.
Чтобы остановить множественную инициализацию ViewModels, поскольку представление объявлено в представлении навигации, а SwiftUI использует структуру, которая является типом значения, поэтому в конечном итоге они инициализируются до представления представления, поэтому вы можете преобразовать это представление в LazyView, поэтому что он будет инициализирован только тогда, когда представление будет представлено или показано.
// Use this to delay instantiation when using `NavigationLink`, etc...
struct LazyView<Content: View>: View {
var content: () -> Content
var body: some View {
self.content()
}
}
Вы можете назвать это так...
NavigationLink(destination: LazyView { ViewTobePresented() })