想象一个具有入职,登录/注册和某种内容的典型应用程序。应用加载后,您需要对要显示的视图做出一些决定。天真的实现可能看起来像这样:
struct ContentView: View {
//assuming some centralized state that keeps track of basic user activity
@State var applicationState = getApplicationState()
var body: some View {
if !applicationState.hasSeenOnboarding {
return OnBoarding()
}
if !applicationState.isSignedIn {
return Registration()
}
return MainContent()
}
}
显然,这种方法失败了,因为SwiftUI视图需要不透明的返回类型some View
。可以使用AnyView
包装器类型来缓解这种情况(尽管有点怪异),该包装器提供了类型擦除功能,并将允许以下代码进行编译。
struct ContentView: View {
//assuming some centralized state that keeps track of basic user activity
@State var applicationState = getApplicationState()
var body: some View {
if !applicationState.hasSeenOnboarding {
return AnyView(OnBoarding())
}
if !applicationState.isSignedIn {
return AnyView(Registration())
}
return AnyView(MainContent())
}
}
是否存在不需要使用AnyView
的更正确的方法? SceneDelegate
中是否有功能可以处理向完全不同的视图层次结构的过渡?
答案 0 :(得分:3)
执行此类操作的最SwiftUI
-y方法可能是使用Group
视图:
import SwiftUI
struct ContentView: View {
@State private var applicationState = getApplicationState()
var body: some View {
Group {
if !applicationState.hasSeenOnboarding {
OnBoarding()
} else if !applicationState.isSignedIn {
Registration()
} else {
MainContent()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
要注意的最重要的一点是,这样一来,您就不会依赖AnyView
进行类型擦除(如果不是绝对必要的话,可以避免使用)。
如果要将初始视图创建封装在一个方法中,请不要使用类型擦除。而是使用some
关键字:
import SwiftUI
struct ContentView: View {
@State private var applicationState = getApplicationState()
private func initialView() -> some View {
if !applicationState.hasSeenOnboarding {
OnBoarding()
} else if !applicationState.isSignedIn {
Registration()
} else {
MainContent()
}
}
var body: some View {
initialView()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
答案 1 :(得分:-1)
我将提取将哪个视图呈现给函数的逻辑:
struct ContentView: View {
@State var applicationState = getApplicationState()
var body: some View {
content()
}
func content() -> AnyView {
guard applicationState.hasSeenOnboarding else {
return AnyView(OnBoarding())
}
guard applicationState.isSignedIn else {
return AnyView(Registration())
}
return AnyView(MainContent())
}
}