将多个子视图传递给 SwiftUI 中的视图
Posted
技术标签:
【中文标题】将多个子视图传递给 SwiftUI 中的视图【英文标题】:Passing multiple subviews to a view in SwiftUI 【发布时间】:2020-11-23 21:19:27 【问题描述】:我创建了一个 Swift 包,它从传递给它的内容数组创建多个 PageTabView:
import SwiftUI
public struct WhatsNewView<Content: View>: View
let content: [Content]
public init(content: [Content])
self.content = content
public var body: some View
TabView
ForEach(0..<content.count, id: \.self) pageNum in
WhatsNewPage(content: content[pageNum], pageNum: pageNum + 1, totalPages: content.count)
.background(Color.white)
.ignoresSafeArea()
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
当我调用它时,我想传入任何类型的简单或复杂视图来填充每个页面。现在,我可以像这样传入一组简单的文本视图:
import SwiftUI
import WhatsNew
@main
struct mFood_Vendor: App
@State var showWhatsNew = false
let whatsNew = WhatsNew()
var page1 = Text("Hello World")
var page2 = Text("Goodbye World")
var body: some Scene
WindowGroup
ContentView()
.fullScreenCover(isPresented: $showWhatsNew, content:
let content = [page1, page2]
WhatsNewView(content: content)
)
.onAppear(perform:
whatsNew.checkForUpdate(showWhatsNew: $showWhatsNew)
)
我希望 page1 和 page2 成为人们希望在 What's New 页面上看到的任何内容。但是,如果我将这些变量更改为任何不同的内容,例如文本和图像,我会收到“无法生成表达式诊断”错误。
理想情况下,我希望能够传递以下内容:
struct page1: View
var body: some View
VStack
Text("something")
Image("plus")
任何帮助将不胜感激。谢谢!
【问题讨论】:
【参考方案1】:您可以使用AnyView
来获得您想要的。在这种情况下,您的代码将变为:
public struct WhatsNewView: View
let content: [AnyView]
public init(content: [AnyView])
self.content = content
public var body: some View
TabView
ForEach(0..<content.count, id: \.self) pageNum in
WhatsNewPage(content: content[pageNum], pageNum: pageNum + 1, totalPages: content.count)
.background(Color.white)
.ignoresSafeArea()
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
并且,作为使用示例:
struct ContentView: View
var body: some View
let view1 = AnyView(Text("Hello World"))
let view2 = AnyView(Image(systemName: "star.fill"))
return WhatsNewView(content: [view1, view2])
编辑:我刚刚发现TabView
可以由TupleView
构建而成。这意味着,根据你的需要,你可以写这样的东西(这很好,因为它不会强迫你的 Swift Package 用户将所有视图包装在 AnyView
中):
import SwiftUI
public struct WhatsNewView<Content: View>: View
private let content: Content
public init(@ViewBuilder contentProvider: () -> Content)
content = contentProvider()
public var body: some View
TabView
content
.background(Color.white)
.ignoresSafeArea()
.tabViewStyle(PageTabViewStyle())
.indexViewStyle(PageIndexViewStyle(backgroundDisplayMode: .always))
你可以这样使用它:
struct ContentView: View
var body: some View
WhatsNewView
Text("Hello World")
Image(systemName: "star.fill")
Color.red
VStack
Text("Text1")
Text("Text2")
Text("Text3")
Button("Tap Me")
print("Tapped")
Group
Text("Group1")
Text("Group2")
结果是:
【讨论】:
【参考方案2】:事实证明,如果我不理会 WhatsNewView,我可以执行以下操作:
struct mFood_Vendor: App
@State var showWhatsNew = false
let whatsNew = WhatsNew()
var page1: some View
VStack (alignment: .leading)
Text("Here is a list of new features:")
Text("Hello World")
Image(systemName: "plus")
var page2: some View
Text("Goodbye World")
var body: some Scene
WindowGroup
ContentView()
.fullScreenCover(isPresented: $showWhatsNew, content:
let content = [AnyView(page1), AnyView(page2)]
WhatsNewView (content: content)
)
.onAppear(perform:
whatsNew.checkForUpdate(showWhatsNew: $showWhatsNew)
)
基本上只是将每个内容页面包装在 AnyView 中。
【讨论】:
看看我的 EDIT,我想它可能对你有用。 甜蜜!我真的很喜欢这个解决方案!谢谢。以上是关于将多个子视图传递给 SwiftUI 中的视图的主要内容,如果未能解决你的问题,请参考以下文章