我正在尝试使用 SwiftUI 创建调查,其中调查可以包含任意数量的问题。
我正在尝试捕获用户通过状态变量输入的值,例如:
@State var answer: String = ""
ForEach(survey) { surveyQuestion in
Text(surveyQuestion.question)
TextField(surveyQuestion.placeholder, text: $answer)
}
但是,由于我事先不知道调查中会有多少问题,因此我不知道这些状态变量中有多少要存储答案。我可以在 ForEach 循环内动态创建变量,但是当我实际提交调查时,这些变量将超出范围(因为提交将发生在 ForEach 循环之外)。
如何创建任意数量的状态变量来捕获用户对调查的回答?
编辑:我曾尝试使我的答案变量成为字典,其中的键是问题的 ID。我的代码看起来像:
@State var answers: [String:String] = [:]
ForEach(survey) { surveyQuestion in
Text(surveyQuestion.question)
TextField(surveyQuestion.placeholder, text: $answers[surveyQuestion.id!])
}
但是,我一直收到错误:
Cannot convert value of type 'Binding<String?>' to expected argument type 'Binding<String>'
然后我尝试将 $answers[surveyQuestion.id!]
替换为 $(answers[surveyQuestion.id!]!)
但随后系统感到困惑并响应为:
'$' is not an identifier; use backticks to escape it
我还尝试调整我的问题模型,以便在同一结构中有一个答案字段。我的代码如下所示:
TextField(surveyQuestion.placeholder, text: $surveyQuestion.answer)
我一直收到错误:
Cannot find '$surveyQuestion' in scope
答案 0 :(得分:1)
使用您添加的编辑中的策略和字典,您可以提供自定义绑定,如下所示:
func bindingForID(id: String) -> Binding<String> {
.init {
answers[id] ?? ""
} set: { newValue in
answers[id] = newValue
}
}
你可以这样使用它:
TextField(surveyQuestion.placeholder, text: bindingForID(id: surveyQuestion.id))
就将此数据添加到 Firestore 而言,您可以在自定义绑定的 set
闭包中触发 Firestore 更新。但是,我可能会建议将此逻辑移动到视图模型 (@Published
) 上的 ObservableObject
属性,您可以在其中使用 Combine 在将数据发送到 Firestore 之前执行诸如 Debouncing 之类的操作(可能有点超出了这个问题的范围)。
答案 1 :(得分:0)
创建一个包含 id、问题和答案的结构体。你的@State var 应该是一个数组。
struct QA: Identifiable {
id: String
question: String
answer: String
}
…
@State private var myQAs: [QA] = myQAs() // or populate them in init, onAppear(if asynchronous) or however you see fit
…
ForEach(myQAs) { qa in
Text(qa.question)
TextField(placeholder, text: $qa.answer)
}