假设我有以下符合View的协议:

protocol Foo: View {
    init(field: Binding<Bool>)
}

然后,我有两个符合该协议的 struct :

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

现在,在我的主要视图中,我有一个符合Foo的类型集合.当我try 初始化这些类型之一的视图时,我得到错误Type 'any Foo' cannot conform to 'View'.我怎么才能避免这种情况?

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

谢谢! (请记住,这只是我试图解决的问题的一个最小例子)

推荐答案

Foo添加一个扩展,它返回一个具体的视图类型-AnyView.

extension Foo {
    static func create(field: Binding<Bool>) -> AnyView {
        AnyView(Self.init(field: field))
    }
}

并在正文中使用此扩展名:

if let fooView = MainView.fooViews.first {
    fooView.create(field: $field)
}

请注意,如果您只需要一个工厂来创建视图,那么可以考虑go 掉这个协议,并使用一个由(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)
    }
}

Swift相关问答推荐

如何在一个角色隔离类上编写自定义==实现?

什么是Swift Concurrency中任务组的正常退出

如何使用swift宏生成一个带有关联值的枚举?

如何使用Swift宏向 struct 体及其init函数添加新成员?

如何设置两个不同的视图模型以在我的SwiftUI应用程序中使用相同的数据源?

如何在自定义视图中读取修改符子元素?

如何在AudioKit中实现自定义音效 node ?

在visionOS RealityView中使用.GenerateText时,未显示Reality Composer Promaterial 纹理

为什么枚举上的.allCases.forEach不是循环(继续和中断不起作用)?

如何在SwiftUI 4+(iOS 16+)中使用新的NavigationStack进行导航

更改 SwiftUI 中按钮矩阵的填充 colored颜色

如何在 SwiftUI 中为过渡动画保持相同的标识

列表不显示信息

如何从我的 macOS 应用程序打开 (.log) 文件?

NavigationStack 和 TabView - 工具栏和标题不显示

我如何从 UIAlertController 导航到新屏幕(swiftUI)

如何删除桥头而不出错?

Swift 中惰性 var 的优势是什么

如何使用 swift 将 Images.xcassets 中的图像加载到 UIImage 中

如何快速格式化用户显示(社交网络等)的时间间隔?