【发布时间】:2020-09-11 00:27:25
【问题描述】:
我们的目标是拥有一个TextField,它在输入字符时接受字符,并将它们显示在TextField 下方的“堆”中。我的意思是,每个新字符都显示在最后一个字符的顶部。将字母堆积起来很容易——我使用ForEach 循环遍历ZStack 内的数组。为了获取数组中的字符,我使用了自定义绑定。它有效,但问题是每次输入新字符时字符都会重复。例如,如果用户键入 CAT,首先会出现 C,然后在 C 的顶部出现 CA,然后在 CA 和 C 的顶部出现 CAT。换句话说,当我只想要三个时,堆叠了六个字符。
struct ContentView: View {
@State private var letter = ""
@State private var letterArray = [String]()
var body: some View {
let binding = Binding<String>(
get: { self.letter },
set: { self.letter = $0
self.letterArray.append(self.letter)
})
return VStack {
TextField("Type letters and numbers", text: binding)
ZStack {
ForEach(letterArray, id: \.self) { letter in
Text(letter)
}
}
}
}
}
更新:
我让这个问题变得更加困难。通过使用ObservableObject,我能够将逻辑与视图分离并简化代码。首先,我创建了一个视图模型。现在,每次用户在TextField 中输入内容时,它都会被didSet 捕获并转换为字符数组。请注意,我必须使用 map 从字符数组转换为字符串数组,因为 ForEach 不适用于字符。
class ViewModel: ObservableObject {
@Published var letterArray = [String]()
@Published var letter = "" {
didSet {
letterArray = Array(letter).map { String($0) }
}
}
}
在ContentView中,我只需要@ObservedObject var vm = ViewModel(),那么我使用vm.letter或vm.letterArray引用变量
【问题讨论】: