0

I have created a simple example of the problem I'm facing. I have two views, ListView and EditView. ListView is observing the UsersViewModel (plural) which contain a list of user names.

Using NavigationLink I want to present a form where I can edit the user name and this is where I'm getting confused. I have created a UserViewModel (singular) which I have the EditView observing, but when I try to call the EditView passing the value from the ForEach loop, I get a type mismatch error as I am not passing a UserViewModel.

Maybe I am misunderstanding the observable object. I thought I could change the user name on the edit form, navigate back to the list view and I would see the change in the list.

struct ListView: View {
    
    // Observe the Users View Model
    @ObservedObject var usersViewModel = UsersViewModel()
    
    var body: some View {
        
        NavigationView {
            List() {
                
                ForEach(usersViewModel.users) { user in

                    // FAILS with cannot converted "user" to expected type userViewModel
                    NavigationLink (destination: EditView(userViewModel: user)) {

                        Text("Hello \(user.name)")
                    }
                }
            }
            .navigationBarTitle("User List", displayMode: .inline)
            .onAppear(){
                usersViewModel.loadUsers()
            }

The edit view

struct EditView: View {

  @ObservedObject var userViewModel: UserViewModel
     var body: some View {
         TextField("User Name", text: $userViewModel.user)
Jmcg
  • 239
  • 2
  • 9

2 Answers2

1

cannot converted "user" to expected type userViewModel

You probably want to use the same UserViewModel in both views (assuming the user is a struct).

Change your EditView to expect a usersViewModel parameter in init:

struct EditView: View {
  @ObservedObject var usersViewModel: UsersViewModel

and pass it in the parent view:

NavigationLink (destination: EditView(usersViewModel: usersViewModel))

Otherwise, as the user is probably a struct, you will modify the different copy of the user in the child view.

pawello2222
  • 46,897
  • 22
  • 145
  • 209
0

I have got around the issue by passing the usersViewModel to the editView rather than userViewModel as pawello2222 suggested, but obviously you need to know which element you want to edit.

So I have done this;

       let users = usersViewModel.users.enumerated().map({ $0 })
        
        NavigationView {
            List() {
                ForEach(users, id: \.element.id ) { index, user in

                    NavigationLink (destination: EditView(userViewModel: usersViewModel, index: index)) {
                        

This seems long winded, surely having to enumerate the viewModel to provide the EditView with an index of which element to edit is not the correct way?

It works, but I would like to know the proper way

Jmcg
  • 239
  • 2
  • 9