为输入到 TextField 中的每个字符调用函数(生成要显示的列表)
Call function (which generates list to be shown) for each character entered into TextField
我希望我的 GUI 能够更新用户在 TextField 中输入的值并对其做出反应。我有一个函数可以将结果计算为字符串数组,然后显示出来。
但是,我无法做到这一点 - 目前我不得不求助于用户在完成输入值时必须按下的提交按钮。
那么,有没有办法对输入的每个数字做出反应?请看我的示例代码!
首先是简单的 GUI:
struct ContentView: View {
@State var initialValue = ""
@ObservedObject var model = ImmediateUpdaterModel()
var body: some View {
VStack{
TextField("Enter value", text: $initialValue)
Button(
action: {model.PopulateListBasedOnInputValue(inputValue: convertTextToDouble(inputString: initialValue))
},
label: {Text("Submit")}
)
ScrollView {
LazyVStack {
ForEach(model.displayData,id: \.self) { myString in
Text("\(myString)")
}
}
}
}
}
然后是包含函数 PopulateListBasedOnInputValue 的 ViewModel:
class ImmediateUpdaterModel: ObservableObject {
@Published var displayData = [String]()
func PopulateListBasedOnInputValue(inputValue: Double) {
displayData.removeAll()
if inputValue<10 {
displayData.append("That is a low value")
} else if inputValue<100 {
displayData.append("That is a medium value")
} else if inputValue<1000 {
displayData.append("That is a high value")
}
displayData.append("However, all values are good!")
init() {
displayData = []
}
最后澄清我想要达到的目标:
如果用户打算写 999,首先显示:
这是一个低值
但是,所有值都很好!
当输入下一个数字时,文本变为
这是一个中值
但是,所有值都很好!
当输入最后一个 9 时,文本变为
这是一个很高的价值
但是,所有值都很好!
添加 ImmediateUpdaterModel
使情况复杂化。你 可以 通过使用 onChange
甚至 Combine
触发 PopulateListBasedOnInputValue
来让它工作,但看起来整个事情可以通过构建来简化它进入 View
:
struct ContentView: View {
@State private var textValue = ""
var body: some View {
VStack{
TextField("Enter value", text: $textValue)
ScrollView {
if !textValue.isEmpty {
if let doubleValue = Double(textValue) {
switch doubleValue {
case _ where doubleValue < 10:
Text("That is a low value")
case _ where doubleValue < 100:
Text("That is a medium value")
case _ where doubleValue >= 100:
Text("That is a high value")
default:
Text("")
}
Text("However, all values are good!")
} else {
Text("Invalid character")
}
}
}
}
}
}
您还可以将逻辑分离到计算的 属性 中,每次 @State
更改时都会得到 re-run。此策略看起来更接近您的原始系统:
struct ContentView: View {
@State private var textValue = ""
var displayedData : [String] {
var toReturn = [String]()
if !textValue.isEmpty {
if let doubleValue = Double(textValue) {
switch doubleValue {
case _ where doubleValue < 10:
toReturn.append("That is a low value")
case _ where doubleValue < 100:
toReturn.append("That is a medium value")
case _ where doubleValue >= 100:
toReturn.append("That is a high value")
default:
break
}
toReturn.append("However, all values are good!")
} else {
toReturn.append("Invalid character")
}
}
return toReturn
}
var body: some View {
VStack{
TextField("Enter value", text: $textValue)
ScrollView {
ForEach(displayedData, id: \.self) { item in //generally, you want to avoid using \.self as an id, but here we can guarantee all of the strings are unique
Text(item)
}
}
}
}
}
我希望我的 GUI 能够更新用户在 TextField 中输入的值并对其做出反应。我有一个函数可以将结果计算为字符串数组,然后显示出来。
但是,我无法做到这一点 - 目前我不得不求助于用户在完成输入值时必须按下的提交按钮。
那么,有没有办法对输入的每个数字做出反应?请看我的示例代码!
首先是简单的 GUI:
struct ContentView: View {
@State var initialValue = ""
@ObservedObject var model = ImmediateUpdaterModel()
var body: some View {
VStack{
TextField("Enter value", text: $initialValue)
Button(
action: {model.PopulateListBasedOnInputValue(inputValue: convertTextToDouble(inputString: initialValue))
},
label: {Text("Submit")}
)
ScrollView {
LazyVStack {
ForEach(model.displayData,id: \.self) { myString in
Text("\(myString)")
}
}
}
}
}
然后是包含函数 PopulateListBasedOnInputValue 的 ViewModel:
class ImmediateUpdaterModel: ObservableObject {
@Published var displayData = [String]()
func PopulateListBasedOnInputValue(inputValue: Double) {
displayData.removeAll()
if inputValue<10 {
displayData.append("That is a low value")
} else if inputValue<100 {
displayData.append("That is a medium value")
} else if inputValue<1000 {
displayData.append("That is a high value")
}
displayData.append("However, all values are good!")
init() {
displayData = []
}
最后澄清我想要达到的目标: 如果用户打算写 999,首先显示:
这是一个低值
但是,所有值都很好!
当输入下一个数字时,文本变为
这是一个中值
但是,所有值都很好!
当输入最后一个 9 时,文本变为
这是一个很高的价值
但是,所有值都很好!
添加 ImmediateUpdaterModel
使情况复杂化。你 可以 通过使用 onChange
甚至 Combine
触发 PopulateListBasedOnInputValue
来让它工作,但看起来整个事情可以通过构建来简化它进入 View
:
struct ContentView: View {
@State private var textValue = ""
var body: some View {
VStack{
TextField("Enter value", text: $textValue)
ScrollView {
if !textValue.isEmpty {
if let doubleValue = Double(textValue) {
switch doubleValue {
case _ where doubleValue < 10:
Text("That is a low value")
case _ where doubleValue < 100:
Text("That is a medium value")
case _ where doubleValue >= 100:
Text("That is a high value")
default:
Text("")
}
Text("However, all values are good!")
} else {
Text("Invalid character")
}
}
}
}
}
}
您还可以将逻辑分离到计算的 属性 中,每次 @State
更改时都会得到 re-run。此策略看起来更接近您的原始系统:
struct ContentView: View {
@State private var textValue = ""
var displayedData : [String] {
var toReturn = [String]()
if !textValue.isEmpty {
if let doubleValue = Double(textValue) {
switch doubleValue {
case _ where doubleValue < 10:
toReturn.append("That is a low value")
case _ where doubleValue < 100:
toReturn.append("That is a medium value")
case _ where doubleValue >= 100:
toReturn.append("That is a high value")
default:
break
}
toReturn.append("However, all values are good!")
} else {
toReturn.append("Invalid character")
}
}
return toReturn
}
var body: some View {
VStack{
TextField("Enter value", text: $textValue)
ScrollView {
ForEach(displayedData, id: \.self) { item in //generally, you want to avoid using \.self as an id, but here we can guarantee all of the strings are unique
Text(item)
}
}
}
}
}