SwiftUI 滑块和绑定提示?

SwiftUI sliders and binding tips?

我正在 SwiftUI 中为 macOS 开发一个图像编辑应用程序,但我觉得我有很多代码重复,应该更优雅一些。

我有一些滑块和一些绑定,以确保值更新并在滑块值更改时调用处理方法。目前我对每个滑块都有一个绑定:

        let vStretch = Binding<Double>(
            get: {
                self.verticalStretchLevel
            },
        
            set: {
                self.verticalStretchLevel = [=10=]
                applyProcessing("vertical stretch")
            }
        )
        
        let straighten = Binding<Double>(
            get: {
                self.straightenLevel
            },
        
            set: {
                self.straightenLevel = [=10=]
                applyProcessing("straighten")
            }
        )
        
        let vignette = Binding<Double>(
            get: {
                self.vignetteLevel
            },
        
            set: {
                self.vignetteLevel = [=10=]
                applyProcessing("vignette")
            }
        )

这很丑吧?任何人都可以指出一些文章、网站或给我一些关于如何做到这一点的建议吗?

提前致谢!

我最终制作了一个滑块视图,它也有绑定:

//
//  SliderView.swift
//
//  Created by Michel Storms on 07/12/2020.
//

import SwiftUI

struct SliderView: View {
    var runFilters: () -> Void // links to function from parent view
    
    let label: String
    let level: Binding<Double>
    
    var body: some View {
        if label.count == 1 {
            HStack {
                Text(label).frame(width: sliderValueWidth)
                Slider(value: intensity(for: level) )
                TextField("", value: level, formatter: sliderFormatter(), onCommit: { self.runFilters() } ).frame(width: sliderValueWidth)
            }
            .onLongPressGesture{ level.wrappedValue = 0.5 ; self.runFilters() }
            .onTapGesture(count: 2, perform: { level.wrappedValue = 0.5 ; self.runFilters() })
            .frame(height: sliderTextSize)
            .font(.system(size: sliderTextSize))
        } else {
            VStack {
                HStack{
                    Text(label)
                    Spacer()
                    TextField("", value: level, formatter: sliderFormatter(), onCommit: { self.runFilters() } ).frame(width: sliderValueWidth)
                }
                .frame(height: sliderTextSize)
                .font(.system(size: sliderTextSize))
                
                Slider(value: intensity(for: level) ).frame(height: sliderTextSize)
            }
            .onLongPressGesture{ level.wrappedValue = 0.5 ; self.runFilters() }
            .onTapGesture(count: 2, perform: { level.wrappedValue = 0.5 ; self.runFilters() })
            .frame(height: sliderHeight)
            .font(.system(size: sliderTextSize))
        }
    }
    
    func intensity(for sliderLevel: Binding<Double>) -> Binding<Double> {
        Binding<Double>(
            get: { sliderLevel.wrappedValue },
            set: { sliderLevel.wrappedValue = [=10=]; self.runFilters() }
        )
    }
    
    func sliderFormatter() -> NumberFormatter {
        let formatter = NumberFormatter()
        formatter.allowsFloats = true
        formatter.numberStyle = .decimal
        formatter.alwaysShowsDecimalSeparator = true
        formatter.maximumFractionDigits = 2
        formatter.minimumFractionDigits = 2
        formatter.decimalSeparator = "."
        return formatter
    }
}

...然后像这样显示滑块:

var body: some View {
        return List {
            VStack {
                SliderView(runFilters: self.runFilters, label: "Exposure", level: $appState.exposureLevel)
                SliderView(runFilters: self.runFilters, label: "Contrast", level: $appState.contrastLevel)
                SliderView(runFilters: self.runFilters, label: "Brightness", level: $appState.brightnessLevel)
                SliderView(runFilters: self.runFilters, label: "Shadows", level: $appState.shadowsLevel)
                SliderView(runFilters: self.runFilters, label: "Highlights", level: $appState.highlightsLevel)
                SliderView(runFilters: self.runFilters, label: "Vibrance", level: $appState.vibranceLevel)
                SliderView(runFilters: self.runFilters, label: "Saturation", level: $appState.saturationLevel)
                SliderView(runFilters: self.runFilters, label: "Clarity", level: $appState.clarityLevel)
                SliderView(runFilters: self.runFilters, label: "Black Point", level: $appState.blackpointLevel)
                if debug {
                    SliderView(runFilters: self.runFilters, label: "DEBUG / TEST", level: $appState.debugAndTestSliderLevel)
                }
            }
            .font(.system(size: sliderTextSize))