I’m trying to write a protocol that requires conformers to have a View property, or a @ViewBuilder method that returns some View.
I want to have a re-useable composite view that can build different sub views based on what type of data needs to be displayed.
The protocol would look like this…
protocol RowView {
var leftSide: some View { get }
var rightSide: some View { get }
}
That way I could call something like this…
struct Example: RowView {
var id: Int
var leftSide: some View { … }
var rightSide: some View { … }
}
struct ContentView: View {
let rows: [RowView]
var body: some View {
VStack {
Foreach(rows, id: \.id) {
HStack {
$0.leftSide
$0.rightSide
}
}
}
}
}
CodePudding user response:
You need to change the protocol to something like:
protocol RowView {
associatedtype LView: View
associatedtype RView: View
var leftSide: LView { get }
var rightSide: RView { get }
}
Also, use the concrete Example
type in the content view instead of the protocol (the protocol you defined doesn't have id
at all):
let rows: [Example]
Also! you can make the RowView
to be identifiable
as your need, So no need for id: \.id
anymore:
protocol RowView: Identifiable
A working code:
protocol RowView: Identifiable {
associatedtype LView: View
associatedtype RView: View
var leftSide: LView { get }
var rightSide: RView { get }
}
struct Example: RowView {
var id: Int
var leftSide: some View { Text("Left") }
var rightSide: some View { Text("Right") }
}
struct ContentView: View {
let rows: [Example] = [
.init(id: 1),
.init(id: 2)
]
var body: some View {
VStack {
ForEach(rows) { row in
HStack {
row.leftSide
row.rightSide
}
}
}
}
}