Suppose I have the following protocol which conforms to View
:
protocol Foo: View {
init(field: Binding<Bool>)
}
I then have two structs which conform to this protocol:
struct BarView: Foo {
@Binding private var field: Bool
init(field: Binding<Bool>) {
self._field = field
}
var body: some View {
Text(field ? "Some text" : "Some other text")
}
}
struct QuxView: Foo {
@Binding private var field: Bool
init(field: Binding<Bool>) {
self._field = field
}
var body: some View {
Text(field ? "Some text" : "Some other text")
}
}
Now, in my main view I have a collection of types which conform to Foo
. When I try and initialise a view of one of these types, I get the error Type 'any Foo' cannot conform to 'View'
. How do I avoid this?
struct MainView: View {
static let fooViews: [any Foo.Type] = [
BarView.self,
QuxView.self
]
@State private var field = false
var body: some View {
if let fooView = MainView.fooViews.first {
fooView.init(field: $field)
}
}
}
Thanks! (Bear in mind this is a minimal example of the problem I'm trying to solve)
Add an extension to Foo
that returns a concrete view type - AnyView
.
extension Foo {
static func create(field: Binding<Bool>) -> AnyView {
AnyView(Self.init(field: field))
}
}
and use this extension in the body instead:
if let fooView = MainView.fooViews.first {
fooView.create(field: $field)
}
Note that if all you need is a factory to create views, consider getting rid of the protocol, and jut using an array of (Binding<Bool>) -> AnyView
:
static let fooViewFactories: [(Binding<Bool>) -> AnyView] = [
{ AnyView(BarView(field: $0)) },
{ AnyView(QuxView(field: $0)) },
]
@State private var field = false
var body: some View {
if let factory = MainView.fooViewFactories.first {
factory($field)
}
}