【问题标题】:SwiftUI - Getting TextField to array in ForEachSwiftUI - 在 ForEach 中获取 TextField 数组
【发布时间】: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.lettervm.letterArray引用变量

【问题讨论】:

    标签: foreach binding swiftui


    【解决方案1】:

    我遇到您问题的住宅区,下面的代码可能对您有所帮助 我修改了你的代码如下;

    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)
                }
            }
        }
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2020-06-20
      • 1970-01-01
      • 1970-01-01
      • 2020-06-11
      • 2019-12-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多