I want to define a protocol that has a View Property to be used from my main view hierarchy. I have defined a protocol that returns a @ViewBuilder property wrapper with an associated View type.
//: protocol
//: ========================================================================= ://
protocol SimpleProtocol{
associatedtype BasicView: View
@ViewBuilder var aView:BasicView { get }
}
From the struct of my main View, I define a variable conforming to the protocol and call it's view in the body of the main struct (just to clarify, the any to define the "any SimpleProtocol" was forced by the compiler):
//: the actual view
//: ========================================================================= ://
struct ProtocolTest: View {
var item:any SimpleProtocol
var body: some View {
item.aView
}
}
However I get the following error:
Type 'any View' cannot conform to 'View'
Here is an image of the code showing the error.
Just for clarity, to make the preview work I have created a struct that conforms to the protocol
//: struct conforming to protocol to be used in preview
//: ========================================================================= ://
struct TestItem:SimpleProtocol{
var aView: some View{
Text( "Text from Test Item")
.padding()
}
}
//: preview
//: ========================================================================= ://
struct ProtocolTest_Previews: PreviewProvider {
static var previews: some View {
ProtocolTest(item: TestItem())
}
}
CodePudding user response:
To accomplish this, you can constrain ProtocolTest
with a generic:
struct ContentView: View {
var body: some View {
ProtocolTest(item: A())
}
}
protocol SimpleProtocol{
associatedtype BasicView: View
@ViewBuilder var aView:BasicView { get }
}
struct ProtocolTest<T:SimpleProtocol>: View {
var item: T
var body: some View {
item.aView
}
}
struct A: SimpleProtocol {
var aView: some View {
Text("Test")
}
}
This avoids the issue mentioned in the comments about using any
and allows the compiler to infer at compile time what the actual type of the implementation of SimpleProtocol
will be.
CodePudding user response:
The solution, as suggested by jnpdx, was to change the ProtocolTest as follows:
struct ProtocolTest<T:SimpleProtocol>: View {
var item:T
var body: some View {
item.aView
}
}