如何在 SwiftUI 中为 Int 类型属性创建滑块?

Mel*_*ius 0 slider swiftui

我有一个名为“score”的 Int 属性的视图,我想用滑块调整它。

struct IntSlider: View {
    @State var score:Int = 0

    var body: some View {
        VStack{
            Text(score.description)
            Slider(value: $score, in: 0.0...10.0, step: 1.0)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是 SwiftUI 的 Slider 仅适用于双打/浮动。

我怎样才能让它与我的整数一起工作?

Mar*_*eIV 22

长话短说

作为本页其他答案的替代方案,我提出了一种解决方案,该解决方案利用类型约束的通用扩展方法来简化调用站点。这是您需要做的所有事情的示例:

Slider(value: .convert(from: $count), in: 1...8, step: 1)
Run Code Online (Sandbox Code Playgroud)

这种方法的好处:

  1. 由于泛型/重载,它会自动将任何 Int类型(例如Int, Int8, Int64)转换为任何 Float类型(例如Float, Float16, CGFloat, Double),反之亦然

  2. 将扩展添加到项目(或项目引用的包中)后,您只需调用.convert任何绑定站点,它就会“正常工作”。

  3. 不需要任何其他东西来使用它(即没有“代理”结构、变量或其他本地项目来扰乱您的视图。)您只需直接内联使用它(见上文。)

  4. 当在任何需要 的地方时Binding,只需键入.,代码完成就会自动建议convert作为一个选项。这是有效的,因为每个扩展方法都是在 上定义的Binding,并且它返回 a Binding(即Self) 作为其结果类型,从而使其可以被自动完成系统发现。(对于任何类型的任何此类静态方法都是如此。)

这是前面提到的扩展方法......

public extension Binding {

    static func convert<TInt, TFloat>(from intBinding: Binding<TInt>) -> Binding<TFloat>
    where TInt:   BinaryInteger,
          TFloat: BinaryFloatingPoint{

        Binding<TFloat> (
            get: { TFloat(intBinding.wrappedValue) },
            set: { intBinding.wrappedValue = TInt($0) }
        )
    }

    static func convert<TFloat, TInt>(from floatBinding: Binding<TFloat>) -> Binding<TInt>
    where TFloat: BinaryFloatingPoint,
          TInt:   BinaryInteger {

        Binding<TInt> (
            get: { TInt(floatBinding.wrappedValue) },
            set: { floatBinding.wrappedValue = TFloat($0) }
        )
    }
}
Run Code Online (Sandbox Code Playgroud)

...这是一个可在操场上使用的演示,展示它们的使用情况。
(注意:不要忘记复制上面的扩展方法!)

struct ConvertTestView: View {

    @State private var count: Int = 1

    var body: some View {

        VStack{
            HStack {
                ForEach(1...count, id: \.self) { n in
                    Text("\(n)")
                        .font(.title).bold().foregroundColor(.white)
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(.blue)
                }
            }
            .frame(maxHeight: 64)
            HStack {
                Text("Count: \(count)")
                Slider(value: .convert(from: $count), in: 1...8, step: 1)
            }
        }
        .padding()
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,这是结果......

屏幕截图示例


lor*_*sum 6

struct IntSlider: View {
    @State var score: Int = 0
    var intProxy: Binding<Double>{
        Binding<Double>(get: {
            //returns the score as a Double
            return Double(score)
        }, set: {
            //rounds the double to an Int
            print($0.description)
            score = Int($0)
        })
    }
    var body: some View {
        VStack{
            Text(score.description)
            Slider(value: intProxy , in: 0.0...10.0, step: 1.0, onEditingChanged: {_ in
                print(score.description)
            })
        }
    }
}
Run Code Online (Sandbox Code Playgroud)