SwiftUI:NavigationLink 的目标视图的异构 collection?
SwiftUI: heterogeneous collection of destination views for NavigationLink?
我正在构建不同示例的演示应用程序,我希望根视图是可以导航到不同示例视图的 List
。因此,我尝试创建一个通用的 Example
结构,它可以采用不同的目的地 View
,如下所示:
struct Example<Destination: View> {
let id: UUID
let title: String
let destination: Destination
init(title: String, destination: Destination) {
self.id = UUID()
self.title = title
self.destination = destination
}
}
struct Example1View: View {
var body: some View {
Text("Example 1!")
}
}
struct Example2View: View {
var body: some View {
Text("Example 2!")
}
}
struct ContentView: View {
let examples = [
Example(title: "Example 1", destination: Example1View()),
Example(title: "Example 2", destination: Example2View())
]
var body: some View {
List(examples, id: \.id) { example in
NavigationLink(destination: example.destination) {
Text(example.title)
}
}
}
}
不幸的是,这会导致错误,因为 examples
是异构 collection:
我完全理解为什么它坏了;我正在创建一个异构的示例数组,因为每个 Example
结构都有自己不同的强类型目的地。但我不知道如何实现我想要的,这是一个数组,我可以从中创建一个 List
,其中有许多不同的允许目的地。
我过去曾 运行 遇到过这种事情,过去我通过包装我的通用类型并只公开我需要的确切属性来绕过它(例如,如果我有一个有标题的通用类型,我会制作一个包装器结构和协议,只公开标题,然后制作一个包装器结构的数组)。但是在这种情况下 NavigationLink
本身需要泛型类型,所以没有 属性 我只能以 non-generic 的方式暴露给它。
您可以使用类型擦除包装器 AnyView
。不要使 Example
通用,而是将其中的目标视图设为 AnyView
类型,并在构造 Example
.
时将视图包装在 AnyView
中
例如:
struct Example {
let id: UUID
let title: String
let destination: AnyView
init(title: String, destination: AnyView) {
self.id = UUID()
self.title = title
self.destination = destination
}
}
struct Example1View: View {
var body: some View {
Text("Example 1!")
}
}
struct Example2View: View {
var body: some View {
Text("Example 2!")
}
}
struct ContentView: View {
let examples = [
Example(title: "Example 1", destination: AnyView(Example1View())),
Example(title: "Example 2", destination: AnyView(Example2View()))
]
var body: some View {
NavigationView {
List(examples, id: \.id) { example in
NavigationLink(destination: example.destination) {
Text(example.title)
}
}
}
}
}
我正在构建不同示例的演示应用程序,我希望根视图是可以导航到不同示例视图的 List
。因此,我尝试创建一个通用的 Example
结构,它可以采用不同的目的地 View
,如下所示:
struct Example<Destination: View> {
let id: UUID
let title: String
let destination: Destination
init(title: String, destination: Destination) {
self.id = UUID()
self.title = title
self.destination = destination
}
}
struct Example1View: View {
var body: some View {
Text("Example 1!")
}
}
struct Example2View: View {
var body: some View {
Text("Example 2!")
}
}
struct ContentView: View {
let examples = [
Example(title: "Example 1", destination: Example1View()),
Example(title: "Example 2", destination: Example2View())
]
var body: some View {
List(examples, id: \.id) { example in
NavigationLink(destination: example.destination) {
Text(example.title)
}
}
}
}
不幸的是,这会导致错误,因为 examples
是异构 collection:
我完全理解为什么它坏了;我正在创建一个异构的示例数组,因为每个 Example
结构都有自己不同的强类型目的地。但我不知道如何实现我想要的,这是一个数组,我可以从中创建一个 List
,其中有许多不同的允许目的地。
我过去曾 运行 遇到过这种事情,过去我通过包装我的通用类型并只公开我需要的确切属性来绕过它(例如,如果我有一个有标题的通用类型,我会制作一个包装器结构和协议,只公开标题,然后制作一个包装器结构的数组)。但是在这种情况下 NavigationLink
本身需要泛型类型,所以没有 属性 我只能以 non-generic 的方式暴露给它。
您可以使用类型擦除包装器 AnyView
。不要使 Example
通用,而是将其中的目标视图设为 AnyView
类型,并在构造 Example
.
AnyView
中
例如:
struct Example {
let id: UUID
let title: String
let destination: AnyView
init(title: String, destination: AnyView) {
self.id = UUID()
self.title = title
self.destination = destination
}
}
struct Example1View: View {
var body: some View {
Text("Example 1!")
}
}
struct Example2View: View {
var body: some View {
Text("Example 2!")
}
}
struct ContentView: View {
let examples = [
Example(title: "Example 1", destination: AnyView(Example1View())),
Example(title: "Example 2", destination: AnyView(Example2View()))
]
var body: some View {
NavigationView {
List(examples, id: \.id) { example in
NavigationLink(destination: example.destination) {
Text(example.title)
}
}
}
}
}