Home > Enterprise >  Using protocol to capture SwiftUI view
Using protocol to capture SwiftUI view

Time:07-22

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
                }
            }
        }
    }
}
  • Related