将Slider值绑定到EnvironmentObject

时间:2019-07-12 13:44:45

标签: swiftui combine

说明:

我有一个具有以下层次结构的模型:

  • 食谱
  • ... steps(数组)
  • ... currentStep
  • ...... 参数(数组)
  • .........最低
  • .........最大
  • .........默认值
  • ......... 当前

该模型运行良好。我可以添加步骤,参数,并将当前步骤设置为名为@EnvironmentObject的{​​{1}}。

我创建了一个示例项目here,其中有两个步骤和参数列表,以及三个按钮,可在三个硬编码步骤中添加单个步骤,每个步骤均包含0、1或数组。 3个参数。

顶部列表是步骤行,每个行都是填充底部列表的按钮。底部列表是参数列表,每个参数列表在recipe中包含一个标签和一个滑块。

一切正常,除非我(a)将滑块绑定到模型,并且(b)列表包含的滑块(行)比当前步骤要多。我得到一个VStack

如果我将滑块值绑定到局部变量,则一切正常。以下是相关代码:

index out of range error

同样,项目here是一个可行的示例。

1 个答案:

答案 0 :(得分:1)

我仍在检查您的代码。但我想评论一下您的函数addStepX()中引起我注意的事情:

    func addStep1() {
        let newStep = Step(id: UUID(), name: "Step #1", parameters: [Parameter]())
        currentStep = newStep
        steps.insert(newStep, at: steps.count)
    }

您是否知道steps.insert()不会触发didSet,所以didChange.send()不会执行?我建议您反转顺序并首先插入步骤,然后再更新currentStep。这样,在完成所有更改后,您只需调用一次didChange.send()即可。

    func addStep1() {
        let newStep = Step(id: UUID(), name: "Step #1", parameters: [Parameter]())
        steps.insert(newStep, at: steps.count)
        currentStep = newStep
    }

请注意,更改该选项仍不能解决问题,但是我应该提一下,因为这肯定是一个问题。

更新

更改后,代码看起来更加简洁。而且我似乎找到了一种防止 越界 的方法。

问题似乎是由于计时问题引起的。您的数组已更新,但是列表传递的参数仍然旧。最终,它将赶上来,但是由于无法避免的崩溃,它永远不会实现。那么为什么不使其成为有条件的呢?

请注意,我还将滑块值添加到了Text()视图中,以表明绑定成功:

struct ParameterRow: View {
    @EnvironmentObject var recipe: Recipe
    @State var sliderValue:Float = 30
    var parameter: Parameter!

    init(parameter: Parameter) {
        self.parameter = parameter
    }

    var body: some View {
        VStack {
            Text("\(parameter.name) = \(parameter.id < recipe.currentStep.parameters.count ? recipe.currentStep.parameters[parameter.id].current : -1)")
            Slider(
                value: parameter.id < recipe.currentStep.parameters.count ? $recipe.currentStep.parameters[parameter.id].current : .constant(0),
                from: parameter.minimum,
                through: parameter.maximum,
                by: 1.0
            )
        }
    }
}