Cannot convert Binding<Type> to Binding<Protocol>

In Xcode 12:

I have a protocol:
Code Block swift
protocol Parameter { }

I then have several structs conforming to this protocol:
Code Block swift
struct Temperature: Parameter { }
...

I have a ParameterView that takes a parameter and builds out a view:
Code Block swift
struct ParameterView: View {
@Binding var parameter: Parameter
...
}


Then I have a ParametersView (multiple parameters together now) that uses multiple parameters:

Code Block swift
struct ParametersView: View {
@Binding var temperature: Temperature
 var body: some View {
  VStack(alignment: .leading) {
ParameterView(parameter: $temperature)
...
}
}
}

The compiler does not like this:

Cannot convert value of type 'Binding<Temperature>' to expected argument type 'Binding<Parameter>'

I must be violating something, but being a little rusty, I cannot determine if this is expected behavior or a compiler problem or something I completely messed up.

Any assistance would be appreciated



Answered by OOPer in 617251022
In Swift, Binding<Temperature> and Binding<Parameter> are different types, even when Temperature conforms to Parameter.
This is, sort of current limitation of Swift language, and we are forced to write code under this behavior.

So, you can find this behavior common in Xcode 11.

One workaround is adding a computed property to your Parameter protocol.
Code Block
protocol Parameter {
    var asParameter: Parameter {get set}
}
extension Parameter {
    var asParameter: Parameter {
        get {self as Parameter}
        set {self = newValue as! Self}
    }
}
struct Temperature: Parameter { }
struct ParameterView: View {
    @Binding var parameter: Parameter
    var body: some View {
        //...
    }
}
struct ParametersView: View {
    @Binding var temperature: Temperature
    var body: some View {
        VStack(alignment: .leading) {
            ParameterView(parameter: $temperature.asParameter) //<-
            //...
        }
    }
}


Another way, which I think better is making your ParameterView generic.
Code Block
protocol Parameter { }
struct Temperature: Parameter { }
struct ParameterView<ParameterType>: View
    where ParameterType: Parameter
{
    @Binding var parameter: ParameterType //<-
    var body: some View {
        //...
    }
}
struct ParametersView: View {
    @Binding var temperature: Temperature
    var body: some View {
        VStack(alignment: .leading) {
            ParameterView(parameter: $temperature)
            //...
        }
    }
}


Please try.
Accepted Answer
In Swift, Binding<Temperature> and Binding<Parameter> are different types, even when Temperature conforms to Parameter.
This is, sort of current limitation of Swift language, and we are forced to write code under this behavior.

So, you can find this behavior common in Xcode 11.

One workaround is adding a computed property to your Parameter protocol.
Code Block
protocol Parameter {
    var asParameter: Parameter {get set}
}
extension Parameter {
    var asParameter: Parameter {
        get {self as Parameter}
        set {self = newValue as! Self}
    }
}
struct Temperature: Parameter { }
struct ParameterView: View {
    @Binding var parameter: Parameter
    var body: some View {
        //...
    }
}
struct ParametersView: View {
    @Binding var temperature: Temperature
    var body: some View {
        VStack(alignment: .leading) {
            ParameterView(parameter: $temperature.asParameter) //<-
            //...
        }
    }
}


Another way, which I think better is making your ParameterView generic.
Code Block
protocol Parameter { }
struct Temperature: Parameter { }
struct ParameterView<ParameterType>: View
    where ParameterType: Parameter
{
    @Binding var parameter: ParameterType //<-
    var body: some View {
        //...
    }
}
struct ParametersView: View {
    @Binding var temperature: Temperature
    var body: some View {
        VStack(alignment: .leading) {
            ParameterView(parameter: $temperature)
            //...
        }
    }
}


Please try.
This worked perfectly! Thank you very much!

I need to touch up on Swift generics...
Cannot convert Binding&lt;Type&gt; to Binding&lt;Protocol&gt;
 
 
Q