I have a ListView with a list of users; tapping on each item takes me to the Detail page.
ListView
NavigationStack {
List {
ForEach(viewModel.users) { user in
NavigationLink(value: user) {
Text(user.givenName)
}
}
}
.navigationTitle("UserList")
.navigationDestination(for: User.self, destination: { user in
FormView(user) // this gets called twice, annoying but no solution yet.
})
FormView
@StateObject private var viewModel = ViewModel()
var body: some View {
VStack {
HStack {
TextField("First", text: Binding(
get: { viewModel.user.first ?? "" },
set: { viewModel.user.first = $0 }))
.textFieldStyle(RoundedBorderTextFieldStyle())
.font(.system(size: 16))
.autocapitalization(.none)
TextField("Middle", text: Binding(
get: { viewModel.user.last ?? "" },
set: { viewModel.user.last = $0 }))
.textFieldStyle(RoundedBorderTextFieldStyle())
.font(.system(size: 16))
.autocapitalization(.none)
...
}
}
.onAppear {
viewModel.setUser(user) // deferred set, to ensure ObservableObject is created
// viewModel.user = user // perhaps its not good to set directly
}
...
var user: User
init(_ user: User) {
self.user = user // received the user from the list page
// viewModel.user = user // forbidden by XCode, doesn't compile
}
The user comes from the List page, and I assign it to a local variable first and wait for the view to appear before I set it on the viewModel.
on the ViewModel side, upon breakpoint, I do see that the user was passed and set, only the View is not updating.
ViewModel
class ViewModel: ObservableObject {
@Published var user: User = User(id: 0)
func setUser(_ user: User) {
self.user = user // user
objectWillChange.send() // forcing update - no use
}
Question
-
Main Question is if a change was pushed from
Viewto theObservableObjectand a reaction was expected back in theView, how to do in context of my question. -
This gets called twice on the tap from the list page, another dilemma.
—
.navigationDestination(for: User.self, destination: { user in
FormView(user) // this gets called twice, annoying but no solution yet.
})
Edit – This worked, really?
.onAppear {
// viewModel.setUser(user)
// viewModel.user = user
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
viewModel.user = user
}
}




