使用 SwiftUI 绑定 ViewModel 和 TextFields

Binding ViewModel and TextFields with SwiftUI

我正在寻找在 textfieldsViewModel 之间创建绑定的最佳方法。 目前,我正在为每个文本字段创建一个 @State ,并在需要时手动将值从文本字段发送到 viewModel 属性。我很确定这不是最好的方法...有没有办法将 TextFieldViewModel 属性 绑定?

这是我当前的代码:

struct SigninView: View {
    @State var username:String = ""
    @State var password:String = ""

    var viewModel:SignInViewModel

    var body: some View {
        VStack(alignment: .leading, spacing: 15.0){

            DefaultTextField(placeholder: "username", value: $username)
            DefaultTextField(placeholder: "password", value: $password)

            Spacer()

            FillButton(title:"Sign In"){
                ///// IS THIS CORRECT?
                self.viewModel.email = self.username
                self.viewModel.password = self.password
                //------------------
                self.viewModel.signin()
            }
        }.padding()
    }
}

视图模型类似于:

class SignInViewModel:ObservableObject{

    var username:String? = nil
    var password:String? = nil

这是可能的方法(当然我没有你的自定义视图,所以只是用标准替换,但想法是一样的)。使用 Xcode 11.2/iOS 13.2

测试
class SignInViewModel: ObservableObject{

    @Published var username:String? = nil
    @Published var password:String? = nil
}


struct SigninView: View {
    @ObservedObject var viewModel = SignInViewModel()

    var body: some View {
        VStack(alignment: .leading, spacing: 15.0){

            TextField("username", text: Binding<String>(
                get: {self.viewModel.username ?? ""},
                set: {self.viewModel.username = [=10=]}))
            TextField("password", text: Binding<String>(
                get: {self.viewModel.password ?? ""},
                set: {self.viewModel.password = [=10=]}))

            Spacer()

            Button("Sign In"){
                print("User: \(self.viewModel.username)")
                print("Pass: \(self.viewModel.password)")
            }
        }.padding()
    }
}

backup

我想我们可以用下面的代码简化它。

class SignInViewModel: ObservableObject{
    @Published var username = ""
    @Published var password = ""
}


struct SigninView: View {
    @ObservedObject var viewModel = SignInViewModel()

    var body: some View {
        VStack(alignment: .leading, spacing: 15.0){

            TextField("username", text: $viewModel.username)
            TextField("password", text: $viewModel.password)

            Spacer()

            Button("Sign In"){
                print("User: \(self.viewModel.username)")
                print("Pass: \(self.viewModel.password)")
            }
        }.padding()
    }
}