在 SwiftUI 中创建任意数量的状态变量

时间:2021-07-02 06:04:45

标签: ios swift swiftui

我正在尝试使用 SwiftUI 创建调查,其中调查可以包含任意数量的问题。

enter image description here

我正在尝试捕获用户通过状态变量输入的值,例如:

@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

2 个答案:

答案 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)
}
相关问题