【发布时间】:2021-05-11 22:13:30
【问题描述】:
我是 SwiftUI 的新手。我有一个对象,它具有我想绑定到 UI 中的字段的各种属性。但是,UI 是动态创建的。例如,要包含的字段以及可以自定义的顺序。
在更新对象时无法刷新 UI(例如,当用户输入邮政编码时,我们会自动填充城市和州字段)我创建了一个简化示例。
我可以通过在创建 TextField 时处理每个单独的字段来使其工作,但想看看是否可以更通用。
这是 UI 显示属性的示例对象
class TestObject: ObservableObject {
@Published var testForeignKeyId: Int = 0
@Published var city: String = ""
@Published var state: String = ""
@Published var zip: String = ""
func getStringValue(field: String) -> String {
switch field {
case "City":
return self.city
case "State":
return self.state
case "Zip":
return self.zip
default:
return ""
}
}
func getIntValue(field: String) -> Int {
switch field {
case "TestForeignKeyId":
return self.testForeignKeyId
default:
return 0
}
}
}
示例字段结构:
struct TestField: Identifiable {
let id = UUID().uuidString
var label: String
var fieldType: String
}
如果我这样做并处理每个字段,它就会起作用:
struct ContentView: View {
@ObservedObject var obj: TestObject
var fields: [TestField] = []
@State var stringValue = ""
init() {
self.fields = [TestField(label: "City", fieldType: "Text"), TestField(label: "State", fieldType: "Text"), TestField(label: "Zip", fieldType: "Zip")]
self.obj = TestObject()
}
var body: some View {
List {
ForEach(self.fields) { field in
Text(field.label)
switch field.label {
case "City":
TextField("", text: $obj.city)
case "State":
TextField("", text: $obj.state)
case "Zip":
TextField("", text: $obj.zip,
onEditingChanged: { edit in
if !edit {
// lookup values for zip
self.obj.city = "Test"
self.obj.state = "TT"
}
})
default:
Text(field.label)
}
}
}
}
}
希望能够做这样的事情并基于fieldtype而不是单个字段创建文本字段(因为实际对象具有更多属性):
switch field.fieldType {
case "Text":
Text(field.label)
TextField("", text: self.obj.getStringValue(field: field.label))
case "Zip":
Text(field.label)
TextField("", text: self.obj.getStringValue(field: field.label))
}
但是当我这样做时,我得到了错误:
无法将 String 类型的值转换为预期的参数类型 Binding<String>
我也尝试过使用状态变量,例如
@State var stringValue = ""
然后在文本字段的 .onAppear 中,我将相应属性(obj.state 等)的值分配给stringValue 状态变量。我认为如果更新了observedObject,控件可能会刷新,但不知道在哪里更新stringValue 状态变量以使其正常工作。
希望我解释了我想要做得足够好。有没有人知道如何让它工作?
谢谢
【问题讨论】:
-
正如错误所说,您需要一个绑定(
@Published、@State或@Binding属性)。计算的属性或函数值不能是绑定。通过绑定,SwiftUI 会观察属性并在属性更改时自动更新 UI。在您的第二个代码块中,没有什么可以告诉 SwiftUI 在zip发生更改时更新视图。您可能需要更改您的TestField对象,以便它接受绑定,然后您可以在TextField-TestField(label: "City", fieldType: "Text", fieldValue: $obj.zip)中使用该绑定