我一直在尝试使用SwiftUI复制我的应用程序。它有一个RootViewController,根据枚举值,它显示了一个不同的子视图控制器。与在SwiftUI中一样,我们使用视图代替视图控制器,我的代码如下所示:
struct RootView : View {
@State var containedView: ContainedView = .home
var body: some View {
// custom header goes here
switch containedView {
case .home: HomeView()
case .categories: CategoriesView()
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,我收到警告:
包含控制流语句的闭包不能与function builder一起使用
ViewBuilder
。
因此,是否有其他选择可以切换,以便我可以复制此行为?
Nik*_*nov 31
谢谢大家的回答。我在Apple开发论坛上找到了一种解决方案。基尔·吉拉德(Kiel Gillard)回答了。解决方案是按照Lu_,Linus和Mo的建议在函数中提取开关,但是我们必须包装视图AnyView
才能使其起作用–如下所示:
struct RootView: View {
@State var containedViewType: ContainedViewType = .home
var body: some View {
VStack {
// custom header goes here
containedView()
}
}
func containedView() -> AnyView {
switch containedViewType {
case .home: return AnyView(HomeView())
case .categories: return AnyView(CategoriesView())
...
}
}
Run Code Online (Sandbox Code Playgroud)
ops*_*psb 18
更新:SwiftUI 2 现在支持函数构建器中的 switch 语句,https://github.com/apple/swift/pull/30174
添加到 Nikolai 的答案中,该答案使开关编译但不使用转换,这是他的示例的一个版本,它支持转换。
struct RootView: View {
@State var containedViewType: ContainedViewType = .home
var body: some View {
VStack {
// custom header goes here
containedView()
}
}
func containedView() -> some View {
switch containedViewType {
case .home: return AnyView(HomeView()).id("HomeView")
case .categories: return AnyView(CategoriesView()).id("CategoriesView")
...
}
}
Run Code Online (Sandbox Code Playgroud)
请注意id(...)
已添加到每个 AnyView 的 。这允许 SwiftUI 识别其视图层次结构中的视图,从而允许它正确应用过渡动画。
Ava*_*rio 13
如果指定 a 的返回类型,则似乎不需要将 switch 语句提取到单独的函数中ViewBuilder
。例如:
Group { () -> Text in
switch status {
case .on:
return Text("On")
case .off:
return Text("Off")
}
}
Run Code Online (Sandbox Code Playgroud)
注意:如果您将它们包装起来
AnyView
并将其指定为返回类型,您也可以返回任意视图类型。
Wah*_*don 11
您可以使用ViewBuilder打开枚举。
首先,声明您的枚举:
enum Destination: CaseIterable, Identifiable {
case restaurants
case profile
var id: String { return title }
var title: String {
switch self {
case .restaurants: return "Restaurants"
case .profile: return "Profile"
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后,在视图文件中:
struct ContentView: View {
@State private var selectedDestination: Destination? = .restaurants
var body: some View {
NavigationView {
view(for: selectedDestination)
}
}
@ViewBuilder
func view(for destination: Destination?) -> some View {
switch destination {
case .some(.restaurants):
CategoriesView()
case .some(.profile):
ProfileView()
default:
EmptyView()
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您想使用与NavigationLink相同的情况,可以按如下方式使用:
struct ContentView: View {
@State private var selectedDestination: Destination? = .restaurants
var body: some View {
NavigationView {
List(Destination.allCases,
selection: $selectedDestination) { item in
NavigationLink(destination: view(for: selectedDestination),
tag: item,
selection: $selectedDestination) {
Text(item.title).tag(item)
}
}
}
}
@ViewBuilder
func view(for destination: Destination?) -> some View {
switch destination {
case .some(.restaurants):
CategoriesView()
case .some(.profile):
ProfileView()
default:
EmptyView()
}
}
}
Run Code Online (Sandbox Code Playgroud)
您必须将代码包装在视图中,例如VStack
, 或Group
:
var body: some View {
Group {
switch containedView {
case .home: HomeView()
case .categories: CategoriesView()
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
或者,添加返回值应该有效:
var body: some View {
switch containedView {
case .home: return HomeView()
case .categories: return CategoriesView()
...
}
}
Run Code Online (Sandbox Code Playgroud)
但是,解决此问题的最佳实践方法是创建一个返回视图的方法:
var body: some View {
Group {
switch containedView {
case .home: HomeView()
case .categories: CategoriesView()
...
}
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3404 次 |
最近记录: |