首页 > 解决方案 > 在 SwiftUI 中子类化 TextField 并将状态传递给它

问题描述

我正在尝试对 a 进行子类TextField化以清理代码。我目前在我的 中有一个文本字段“行” Form,但最终我想找到一种方法来使其可扩展(并且有更多HStack的 s)。

Form {
    Section {
        HStack {
            Text("Balance")
                .foregroundColor(Color.white)
            TextField("", text: $balance, onEditingChanged: { (changing) in
                print("Changing: \(changing)")
            }, onCommit: {
                print("Committed!")
            })
            .multilineTextAlignment(.trailing)
            .foregroundColor(Color.white)
            .keyboardType(.numbersAndPunctuation)
            .onReceive(Just(balance)) { newValue in
                    let filtered = newValue.filter { "0123456789".contains($0) }
                    if filtered != newValue {
                        self.balance = filtered
                }
            }
            .placeHolder(
                Text("$0.00")
                    .frame(maxWidth: .infinity, alignment: .trailing)
                    .multilineTextAlignment(.trailing)
                    .foregroundColor(Color(#colorLiteral(red: 0.3492315412, green: 0.3486715555, blue: 0.3704651594, alpha: 1))),
                show: balance.isEmpty)
        }
    }
    .listRowBackground(Color(#colorLiteral(red: 0.1923851669, green: 0.1917944849, blue: 0.2135801911, alpha: 1)))
}

我不想重复HStack声明 4 次(行数)。所以我需要子类化。但是,我需要找到一种将状态(美元符号)传递给子类的方法。如何?另外,有没有办法让我可以使用一个状态数组ForEach?例子:

var imaginaryArrayWithStates = [$textFieldValue1, $textFieldValue2] // you can't do this, but I would like to iterate states somehow...

// ...so that I can use a ForEach
ForEach(imaginaryArrayWithStates) { state
    MyCustomTextField() // how do I pass the state to this subclass? 
}

标签: swiftswiftui

解决方案


您可以使用@Binding

struct CustomTextField: View {
    @Binding var value: String

    var body: some View {
        HStack {
            Text("Balance") // can be extracted as a variable
            TextField("", text: $value, onEditingChanged: { changing in
                print("Changing: \(changing)")
            }, onCommit: {
                print("Committed!")
            })
                .multilineTextAlignment(.trailing)
                .keyboardType(.numbersAndPunctuation)
                .onReceive(Just(value)) { newValue in
                    let filtered = newValue.filter { "0123456789".contains($0) }
                    if filtered != newValue {
                        self.value = filtered
                    }
                }
        }
    }
}
struct ContentView: View {
    @State var values = ["312", "222", ""]

    var body: some View {
        Form {
            Section {
                ForEach(values.indices, id: \.self) { index in
                    CustomTextField(value: self.$values[index])
                }
            }
        }
    }
}

推荐阅读