SwiftUI - Getting TextField to array in ForEach

爷,独闯天下 提交于 2021-01-29 07:36:29

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!