Issue with viewModel and TextField

Viewed 130

I'm not sure whether it's a SwiftUI bug or it's my fault:

When I type some text in a TextField and press the return button on my keyboard (in order to hide my keyboard), the typed text is removed and the TextField is empty again. I've tried this solution on different simulators and on a real device as well. The issue appears every time. I'm using iOS 14.3, Xcode 12.4

TextField view:

struct CreateNewCard: View {
    @ObservedObject var viewModel: CreateNewCardViewModel
    var body: some View {
        TextField("placeholder...", text: $viewModel.definition)
            .foregroundColor(.black)
    }
}

ViewModel:

class CreateNewCardViewModel: ObservableObject {
    @Published var definition: String = "" 
}

Main View:

struct MainView: View {
    @State var showNew = false

    var body: some View {
    Button(action: { showNew = true }, label: { Text("Create") })
        .sheet(isPresented: $showNew, content: {
            CreateNewCard(viewModel: CreateNewCardViewModel())
        })
    }
}

@SwiftPunk: Here is my second question:

Let's say my view model has an additional parameter (id):

class CreateNewCardViewModel: ObservableObject {
    @Published var id: Int
    @Published var definition: String = "" 
}

This parameter needs to be passed when I create the view to my viewModel. For this example let's say we iterate over some elements that have the id:

struct MainView: View {
@State var showNew = false

var body: some View {
ForEach(0...10, id: \.self) { index in // <<<---- this represents the id
    Button(action: { showNew = true }, label: { Text("Create") })
        .sheet(isPresented: $showNew, content: {
            // now I have to pass the id, but this 
            // is the same problem as before 
            // because now I create every time a new viewModel, right?
            CreateNewCard(viewModel: CreateNewCardViewModel(id: index))  
        })
    }
}
1 Answers

Your issue is here, that you did not create a StateObject in main View, and every time you pressed the key on keyboard you created a new model which it was empty as default!

import SwiftUI

struct ContentView: View {
    
    @State var showNew = false
    
    @StateObject var viewModel: CreateNewCardViewModel = CreateNewCardViewModel()  // <<: Here

    var body: some View {
    Button(action: { showNew = true }, label: { Text("Create") })
        .sheet(isPresented: $showNew, content: {
            CreateNewCard(viewModel: viewModel)
        })
    }
}

struct CreateNewCard: View {

    @ObservedObject var viewModel: CreateNewCardViewModel

    var body: some View {

        TextField("placeholder...", text: $viewModel.definition)
            .foregroundColor(.black)

    }
}

class CreateNewCardViewModel: ObservableObject {
    @Published var definition: String = ""
}
Related