[英]Dynamically access TextField in SwiftUI
我正在 VStack 中动态创建一个 TextField。 这里 TextFields 的创建如下:
struct Input: View {
var title: String
@State var value:String
var disableInputMode:Bool = true
var body: some View {
VStack {
Text(title)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color("SecondaryTextColor"))
TextField("", text: $value)
.disabled(disableInputMode)
.frame(maxWidth: .infinity, alignment: .leading)
Divider()
}
.padding()
}
}
这些 TextFields 依赖于其他一些数据字段(在运行时决定):
ScrollView {
VStack {
ForEach(detailsViewModel.details) { datum in
Input(title: datum.title, value: datum.detail!)
}
}.frame(maxWidth: .infinity)
.padding()
}.background(Color("Light"))
.cornerRadius(25)
.padding()
现在,当用户输入数据并尝试应用时,我找不到如何从其他视图获取这些输入。 从本例中的示例 - 从上面的视图。
使用onChange修饰符检测 TextField 值更改并将其更新为您的 model。
struct Input: View {
var title: String
@State var value:String
var disableInputMode:Bool = false
var onTextChange: ((String) -> Void)?
var body: some View {
VStack {
Text(title)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color("SecondaryTextColor"))
TextField("", text: $value)
.onChange(of: value) {
// Called each time value changes.
if onTextChange != nil {
onTextChange!($0)
}
}
.disabled(disableInputMode)
.frame(maxWidth: .infinity, alignment: .leading)
Divider()
}
.padding()
}
}
扩展绑定以处理自定义 onChange
extension Binding {
func onChange(_ handler: @escaping (Value) -> Void) -> Binding<Value> {
Binding(
get: { self.wrappedValue },
set: { newValue in
self.wrappedValue = newValue
handler(newValue)
}
)
}
}
然后你的输入视图变成
struct Input: View {
var title: String
@State var value:String
var disableInputMode:Bool = false
var onTextChange: ((String) -> Void)?
var body: some View {
VStack {
Text(title)
.frame(maxWidth: .infinity, alignment: .leading)
.foregroundColor(Color("SecondaryTextColor"))
TextField("", text: $value.onChange(textChanged))
.disabled(disableInputMode)
.frame(maxWidth: .infinity, alignment: .leading)
Divider()
}
.padding()
}
func textChanged(to value: String) {
// Called each time value changes.
if onTextChange != nil {
onTextChange!(value)
}
}
}
这两种解决方案都可以使用您的输入视图,如下所示。
ScrollView {
VStack {
ForEach(detailsViewModel.details) { datum in
Input(title: datum.title, value: datum.detail) { newValue in
// Each time you will get the update
// Do what ever you want to do with the new value
// something like
// detailsViewModel.update(value: newValue, forItem: datum.id)
print("Text value for \(datum.id) :", newValue)
}
}
}.frame(maxWidth: .infinity)
.padding()
}.background(Color("Light"))
.cornerRadius(25)
.padding()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.