【发布时间】:2020-07-05 21:24:32
【问题描述】:
我是 iOS 和 UI 新手,我正在为我的女儿编写一个简单的应用程序来帮助她制作柠檬水。三个滑块控制成分(水、糖、柠檬)和两个控制口味参数(酸甜)。这个想法是,对于给定的甜度和酸度,调整任何成分滑块将更新其他滑块以满足指定的甜度和酸度。可以看到如下效果:
如您所见,我已经成功了,但这不是一个很好的解决方案;视图中的一切都以一种非常紧迫的方式发生,滑块值的变化推动了对updateIngredients()的调用。
struct ContentView: View {
// Initial state recipe is 200g sugar, 1400ml water, 7 lemons
@State var numLemons: Double = 7
@State var sugarWeight: Double = 200
@State var waterWeight: Double = 1400
@State var lemonWaterRatio: Double = 7/1400
@State var sugarWaterRatio: Double = 200/1400
...
// Example slider
Text("Lemons: \(numLemons, specifier: "%.0f")")
Slider(value: Binding(get: {
self.numLemons
}, set: { (newVal) in
self.numLemons = newVal
self.updateIngredients("lemons")
}), in: 0...40, step: 1)
我希望有一个视图模型句柄来确定要显示的值,并且模型处理每次任何滑块值更改时重新计算成分,但我无法弄清楚如何在不陷入无限循环的情况下重新计算所有成分。
我已经制作了视图模型Observable 并发布了它的属性,并将这些属性绑定到滑块值。这可以。为了简单起见,我将跳过模型并将成分重新计算放在视图模型中:
struct ContentView: View {
@ObservedObject var display: DisplayCalculator
...
VStack {
Text("Lemons: \(display.numLemons, specifier: "%.0f")")
Slider(value: $display.numLemons, in: display.lemons["minValue"]!...display.lemons["maxValue"]!, step: display.lemons["step"]!)
...
}
// View Model
class DisplayCalculator: ObservableObject {
// Initial state recipe is 200g sugar, 1400ml water, 7 lemons
@Published var numLemons: Double = 7
@Published var sugarWeight: Double = 200
@Published var waterWeight: Double = 1400
@Published var lemonWaterRatio: Double = 7/1400
@Published var sugarWaterRatio: Double = 200/1400
let lemons: Dictionary<String, Double> = [ "minValue": 0, "maxValue": 40, "step": 1]
...
// How can I call this?
func updateIngredients(_ ingredient: String) {
switch(ingredient) {
case "lemons":
// Set self.sugarWeight and self.waterWeight based on self.lemonWaterRatio and self.sugarWaterRatio
...
}
}
...
}
我遇到的问题是,每次其中一个值发生变化时,我都需要重新计算整组值。我知道触发重新计算的唯一方法是从已发布属性上的willSet 驱动它。但是所有属性都需要willSet,因此当重新计算更新所有其他值时,那些属性观察器会无限触发。
是否有可能让任何滑块能够更新所有其他滑块,而无需从滑块本身驱动计算?
【问题讨论】: