如何返回通过SwiftUI中的另一个协议间接继承View协议的结构?

n7taea2i  于 2023-03-11  发布在  Swift
关注(0)|答案(1)|浏览(101)

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

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

然后,我有两个符合此协议的结构体:

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的类型集合。当我尝试初始化其中一个类型的视图时,我得到了错误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)
        }
    }
}

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

ffscu2ro

ffscu2ro1#

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

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

相关问题