为输入到 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)
                }
            }
        }
    }
}