我正在构建一个SwiftUI macOS应用程序,它可以操作一组视图(“Playground”)。每个Playground都有一些特定的信息,但都共享一个通用的公共视图。我还希望枚举列出我的应用程序中所有可用的视图。
我努力使用Swift存在类型和协议来建模我的数据结构。特别是,我总是以错误“Type any View can not conform to protocol View”结束,尽管我读过许多关于存在类型的文档和博客文章,以及为什么协议不能符合自身。我在这一点上受阻。
下面是我的代码:
// the protocol all my playgrounds must implement
protocol PlaygroundComponent {
associatedtype Body: View
@ViewBuilder var component: Self.Body { get }
}
// a generic type that implements the common part of all the playgrounds + the specific part from subtypes
struct PlaygroundView<Content: PlaygroundComponent>: View {
let content : Content
var body: some View {
Text("reused content")
content.component
}
}
// a concrete playground, it defines only the specific part
struct ListModelsPlayground: PlaygroundComponent {
var component: some View {
Text("ListModelsPlayground")
}
}
// an enum that lists all the implementations I have (only one to keep this example short)
enum Playgrounds {
case listModels
var info: any PlaygroundView<PlaygroundComponent> { ListModelsPlayground() } // ---> compilation error : Type 'any PlaygroundComponent' cannot conform to 'PlaygroundComponent'
}
我如何建模一个带有单个子组件的通用视图,以便以后成为这种结构或List( ForEach { } )
SwiftUI视图的一部分?
1条答案
按热度按时间4xrmg8kj1#
首先,
PlaygroundComponent
只是重新发明了View
。你不需要如果Playground组件有一些您想要建模的公共属性,那就是 data,它们不属于视图。如果每个Playground都有自己独特的属性,那就是@State
。作为一个例子,让我们实现两个playgrounds views:
现在假设您需要一个枚举,以便将这些playground放入一个数组中,并以
List
或其他格式显示它们。这就是 data,这就是PlaygroundComponent
s的公共属性所在。请注意,如果公共属性可以更改,则应该使用
struct
,其中static let
s表示每种类型的Playground。现在,我们可以在
List
中显示数组Playground.allCases
,也可以在NavigationSplitView
中显示数组Playground.allCases
,因此单击其中一个会转到PlaygroundView
。注意
PlaygroundView
如何只需要一个playground
。这就是它真正需要的-数据。它可以用它来决定显示哪个Playground。如果你真的不喜欢这个
switch
,你可以将它作为一个属性提取到枚举中: