问题
The goal is to have a TextField that takes characters as they're being entered and display them below the TextField in a 'pile'. By pile I mean, each new character is displayed on top of the last one. Piling the letters up is easy enough - I use ForEach to loop over an array inside a ZStack. To get the characters in the array, I used a custom binding. It works, but the problem is that the characters get repeated each time a new character is typed. For example, if the user types CAT, first the C will appear, then CA on top of the C, then CAT on top of the CA and the C. In other words, there are six characters stacked up when I only wanted three.
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)
                }
            }
        }
    }
} 
UPDATE:
I was making the problem a little more difficult that it was. By using an ObservableObject I was able to separate the logic from the view AND simplify the code. First I created a view model. Now, each time the user types something into a TextField, it's it's caught by didSet and converted into an array of characters. Note, I had to use map to convert from a character array to a string array because ForEach doesn't work with characters.
class ViewModel: ObservableObject {
    @Published var letterArray = [String]()
    @Published var letter = "" {
        didSet {
            letterArray = Array(letter).map { String($0) }
        }
    }
}
In ContentView, I only need @ObservedObject var vm = ViewModel()Then I refer to the variables using vm.letter or vm.letterArray
回答1:
Uptown where I get your problem may the below code help you I modified your code as below;
struct ContentView: View {
@State private var letter = ""
@State private var letterCounter = 0
@State private var letterArray = [String]()
var body: some View {
    let binding = Binding<String>(
        get: { self.letter },
        set: { self.letter = $0
            if self.letter.count > self.letterCounter {
                if let lastLetter = self.letter.last{
                    self.letterArray.append(String(lastLetter))
                }
            }else{
                _ = self.letterArray.removeLast()
            }
            self.letterCounter = self.letter.count
    })
    return VStack {
        
    TextField("Type letters and numbers", text: binding)
        VStack {
            ForEach(letterArray, id: \.self) { letter in
                Text(letter)
            }
        }
    }
}
}
来源:https://stackoverflow.com/questions/63839270/swiftui-getting-textfield-to-array-in-foreach