Home > other >  Let swift @Binding accept any value conforming to `BinaryFloatingPoint`?
Let swift @Binding accept any value conforming to `BinaryFloatingPoint`?

Time:12-21

I have the following code:

class MyModel:ObservableObject {
    
    @Published var time:Double = 0
        
}


struct ContentView: View {
    
    @StateObject var model = MyModel()

    @State var someValue:Float = 0

    var body: some View {
        
        TView(value: $model.time)

    }
}


struct TView: View {
    
    @Binding var value:Float
    
    var body: some View {
        
        Text("value: \(value)")
        
    }
}

Obvisouly that code cannot work because the binding wants a Float and model.time is a Double. Error: Cannot convert value of type 'Binding<Double>' to expected argument type 'Binding<Float>'.

I'd like to mimic what Slider does, where it can bind to values as long as they conform to BinaryFloatingPoint.

I looked at Swift.Math.Floating and Double does conform to BinaryFloatingPoint.

...
extension Double : BinaryFloatingPoint {
...

Looking at the Slider init:

init<V>(value: Binding<V>, in bounds: ClosedRange<V> = 0...1, onEditingChanged: @escaping (Bool) -> Void = { _ in }) where V : BinaryFloatingPoint, V.Stride : BinaryFloatingPoint

How can I change TView, so that it can bind to any type conforming to BinaryFloatingPoint.

My objective is to do what Slider does, allowing me to pass in a Double, Float, etc...

I tried to change TView to:

struct TView: View {
    
    @Binding var value:Float
    
    init<V>(theValue:Binding<V>) where V : BinaryFloatingPoint {
        self._value = theValue
    }
    
    var body: some View {
        
        Text("value: \(value)")
        
    }
}

But, it errors: Cannot assign value of type 'Binding<V>' to type 'Binding<Float>'

How can I change things so that TView can bind to any value conforming to BinaryFloatingPoint?

CodePudding user response:

Move generics to view declaration level, like

struct TView<V: BinaryFloatingPoint>: View {       // << here !!

    @Binding var value:V                           // << here !!

    init(value:Binding<V>) {                       // << here !!
        self._value = value
    }

    var body: some View {
        Text("value: \(Double(value))")
    }
}

Tested with Xcode 13 / iOS 15

  • Related