Reputation: 804
I am looking to structure a SwiftUI component in a similar way as some of Apple's implementations (E.g. Button). I am looking to have a label associated to this component (which is just another View) or have the ability to construct using just a string (and default to using a Text view).
This is what I have:
struct ExampleComponent<Label> : View where Label : View {
let label: () -> Label
let action: () -> ()
init(_ title: String, action: @escaping () -> ()) {
self.init(label: {
Text(title)
}, action: action)
}
init(@ViewBuilder label: @escaping () -> Label, action: @escaping () -> ()) {
self.label = label
self.action = action
}
var body: some View {
label()
}
}
However, this cannot compile due to the error:
Cannot convert value of type 'Text' to closure result type 'Label'.
What's going wrong?
Upvotes: 0
Views: 222
Reputation: 299565
If you want this to be a default, then you need to make sure it only applies in cases where Label == Text
. In other situations, you can't use it. I generally do this with a constrained extension:
extension ExampleComponent where Label == Text {
init(_ title: String, action: @escaping () -> ()) {
self.init(label: {
Text(title)
}, action: action)
}
}
But you can also add the constraint on the init
directly:
init(_ title: String, action: @escaping () -> ()) where Label == Text {
self.init(label: {
Text(title)
}, action: action)
}
Upvotes: 1