简体   繁体   English

使用协议捕获 SwiftUI 视图

[英]Using protocol to capture SwiftUI view

I'm trying to write a protocol that requires conformers to have a View property, or a @ViewBuilder method that returns some View.我正在尝试编写一个协议,该协议要求conformers 有一个View 属性,或者一个返回一些View 的@ViewBuilder 方法。

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

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):此外,在内容视图中使用具体的Example类型而不是协议(您定义的协议根本没有id ):

let rows: [Example]

Also!还! you can make the RowView to be identifiable as your need, So no need for id: \.id anymore:您可以根据需要使RowViewidentifiable ,因此不再需要id: \.id

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM