SwiftUI:仅当输入不为空时启用保存按钮
SwiftUI: Enable save button only when the inputs are not empty
我有一个包含两个文本字段和一个保存按钮的视图。我怎样才能根据文本字段的内容更改按钮的状态(我只想在所有文本字段都不为空的情况下启用按钮)?这是我当前的代码:
// The variables associated with text fields
@State var name: String = ""
@State var type: String = ""
// I'd like to associate this variable with
// my button's disabled / enabled state,
// but the function responsible for it doesn't accept bindings
@State var canSave: Bool = false
var body: some View {
Form {
TextField("Name", text: $name)
TextField("Type", text: $type)
Button(action: {
// ...
}, label: {
Text("Save")
})
.disabled(!canSave) // no bindings allowed here; what to use indead?
}
}
我有一个想法,我应该使用最新的 Combine 框架中的 combineLatest
。但是无论我尝试 google 都会将我引向与 RxSwift 相关的主题,而不是实际的 Combine 实现。
您似乎对 SwiftUI 的工作原理有误解。它不依赖于绑定的下坡数据流。它完全取决于状态变量。 Uphill flow 取决于绑定,但您已经在需要它们的地方获得了它们(除非您的代码是错误的:您已将两个文本字段绑定到相同的绑定)。
所以在像这样的简单情况下,您不需要绑定或组合。你有状态变量,这就是你所需要的:
struct ContentView: View {
@State var name: String = ""
@State var type: String = ""
var body: some View {
Form {
TextField("Name", text: $name)
TextField("Type", text: $type)
Button(action: {
// ...
}, label: {
Text("Save")
}).disabled(name.isEmpty || type.isEmpty)
}
}
}
现在,如果您有许多文本字段要验证而不是一两个,那么当然,您可以使用发布和订阅将它们组合成一个 Bool。但是让我们先把基本原则弄好。
您可以在视图的末尾添加一些代码。这只是为了简单的逻辑,否则,您可能需要创建一些模型。
var body: some View {
Form {
TextField("Name", text: $name)
TextField("Type", text: $type)
Button(action: {
// ...
}, label: {
Text("Save")
})
.disabled(!canSave) // no bindings allowed here; what to use indead?
}.onReceive(Publishers.CombineLatest(Just( name.isEmpty), Just(type.isEmpty))){
self.canSave = !([=10=].0 || [=10=].1)
}
我有一个包含两个文本字段和一个保存按钮的视图。我怎样才能根据文本字段的内容更改按钮的状态(我只想在所有文本字段都不为空的情况下启用按钮)?这是我当前的代码:
// The variables associated with text fields
@State var name: String = ""
@State var type: String = ""
// I'd like to associate this variable with
// my button's disabled / enabled state,
// but the function responsible for it doesn't accept bindings
@State var canSave: Bool = false
var body: some View {
Form {
TextField("Name", text: $name)
TextField("Type", text: $type)
Button(action: {
// ...
}, label: {
Text("Save")
})
.disabled(!canSave) // no bindings allowed here; what to use indead?
}
}
我有一个想法,我应该使用最新的 Combine 框架中的 combineLatest
。但是无论我尝试 google 都会将我引向与 RxSwift 相关的主题,而不是实际的 Combine 实现。
您似乎对 SwiftUI 的工作原理有误解。它不依赖于绑定的下坡数据流。它完全取决于状态变量。 Uphill flow 取决于绑定,但您已经在需要它们的地方获得了它们(除非您的代码是错误的:您已将两个文本字段绑定到相同的绑定)。
所以在像这样的简单情况下,您不需要绑定或组合。你有状态变量,这就是你所需要的:
struct ContentView: View {
@State var name: String = ""
@State var type: String = ""
var body: some View {
Form {
TextField("Name", text: $name)
TextField("Type", text: $type)
Button(action: {
// ...
}, label: {
Text("Save")
}).disabled(name.isEmpty || type.isEmpty)
}
}
}
现在,如果您有许多文本字段要验证而不是一两个,那么当然,您可以使用发布和订阅将它们组合成一个 Bool。但是让我们先把基本原则弄好。
您可以在视图的末尾添加一些代码。这只是为了简单的逻辑,否则,您可能需要创建一些模型。
var body: some View {
Form {
TextField("Name", text: $name)
TextField("Type", text: $type)
Button(action: {
// ...
}, label: {
Text("Save")
})
.disabled(!canSave) // no bindings allowed here; what to use indead?
}.onReceive(Publishers.CombineLatest(Just( name.isEmpty), Just(type.isEmpty))){
self.canSave = !([=10=].0 || [=10=].1)
}