【问题标题】:SwiftUI: Displaying slider position in a seperate labelSwiftUI:在单独的标签中显示滑块位置
【发布时间】:2019-11-23 08:41:47
【问题描述】:

这个问题是SwiftUI: How to get continuous updates from Slider的后续问题

基本上我有一个滑块,它是许多滑块之一。每个 on 都会更改模型类上的一个参数,因此我传入一个绑定,该绑定表示模型类上的特定属性。这是因为每次滑块移动时模型都会获取新值。

struct AspectSlider: View {

    private var value: Binding<Double>

    init(value: Binding<Double>, hintKey: String) {
        self.value = value
    }

    var body: some View {
        VStack(alignment: .trailing) {
            Text("\(self.value.value)")
            Slider(value: Binding<Double>(getValue: { self.value.value }, setValue: { self.value.value = $0 }),
                    from: 0.0, through: 4.0, by: 0.5)
        }
    }
}

无法正常工作的是Text("\(self.value.value)") 显示,它旨在显示滑块的当前值。当 Binding&lt;Double&gt; 值更改时,它不会更新。

相反,它仅在显示屏上的其他内容触发显示屏刷新时才会更新。在我的例子中,代表模型计算结果的标签(当滑块改变它的值时,它不一定会改变)。

我已确认模型正在发生更改,因此绑定正在更新。我的问题是为什么 Text 标签没有立即更新。

【问题讨论】:

  • 它对我有用。你能告诉我们你是如何实例化 AspectSlider 视图的吗?

标签: swiftui


【解决方案1】:

好的,我已经弄清楚为什么我的代码没有按应有的方式更新。它归结为我的模型,看起来像这样(简单版):

final class Calculator: BindableObject {

    let didChange = PassthroughSubject<Int, Never>()
    var total: Int = 0
    var clarity: Double = 0.0 { didSet { calculate() }}

    private func calculate() {
        if newValue.rounded() != Double(total) {
            total = Int(newValue)
            didChange.send(self.total)
        }
    }
}

发生的情况是边栏上的值仅在此模型执行 didChange.send(self.total) 行时才更新。我认为,如果我做对了,那是因为标签正在监视绑定,只有当绑定更新时,标签才会更新。说得通。还在解决这个问题。

我想这是了解 Combine 及其工作原理的一部分 :-)

【讨论】:

    【解决方案2】:

    您的代码,如果像这样调用,可以正常工作:

    struct ContentView: View {
        @State private var value: Double = 0
    
        var body: some View {
            AspectSlider(value: $value, hintKey: "hint")
        }
    }
    
    struct AspectSlider: View {
    
        private var value: Binding<Double>
    
        init(value: Binding<Double>, hintKey: String) {
            self.value = value
        }
    
        var body: some View {
            VStack(alignment: .trailing) {
                Text("\(self.value.value)")
                Slider(value: Binding<Double>(getValue: { self.value.value }, setValue: { self.value.value = $0 }),
                       from: 0.0, through: 4.0, by: 0.5)
            }
        }
    }
    

    请注意,您还可以利用属性包装器@Binding,以避免使用self.value.value。您的实现应该略有改变:

    struct AspectSlider: View {
        @Binding private var value: Double
    
        init(value: Binding<Double>, hintKey: String) {
            self.$value = value
        }
    
        var body: some View {
            VStack(alignment: .trailing) {
                Text("\(self.value)")
                Slider(value: Binding<Double>(getValue: { self.value }, setValue: { self.value = $0 }),
                       from: 0.0, through: 4.0, by: 0.5)
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-09
      • 2021-12-14
      • 1970-01-01
      • 1970-01-01
      • 2016-08-24
      • 2021-09-13
      • 1970-01-01
      相关资源
      最近更新 更多