Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI ViewModel published property and binding

My question is probably the result of a misunderstanding but I can't figure it out, so here it is:

When using a component like a TextField or any other component requiring a binding as input

TextField(title: StringProtocol, text: Binding<String>)

And a View with a ViewModel, I naturally thought that I could simply pass my ViewModel @Published properties as binding :

class MyViewModel: ObservableObject { 
     @Published var title: String
     @Published var text: String
}

// Now in my view
var body: some View {
    TextField(title: myViewModel.title, text: myViewModel.$text)
}

But I obviously can't since the publisher cannot act as binding. From my understanding, only a @State property can act like that but shouldn't all the @State properties live only in the View and not in the view model? Or could I do something like that :

class MyViewModel: ObservableObject { 
     @Published var title: String
     @State var text: String
}

And if I can't, how can I transfer the information to my ViewModel when my text is updated?

like image 451
Wimps Avatar asked Apr 27 '20 22:04

Wimps


1 Answers

You were almost there. You just have to replace myViewModel.$text with $myViewModel.text.

class MyViewModel: ObservableObject {
    
    var title: String = "SwiftUI"
    
    @Published var text: String = ""
}

struct TextFieldView: View {
    
    @ObservedObject var myViewModel: MyViewModel = MyViewModel()
    
    var body: some View {
        TextField(myViewModel.title, text: $myViewModel.text)
    }
}

TextField expects a Binding (for text parameter) and ObservedObject property wrapper takes care of creating bindings to MyViewModel's properties using dynamic member lookup.

like image 151
sElanthiraiyan Avatar answered Nov 06 '22 04:11

sElanthiraiyan