使用 SwiftUI 在不同的 UI 层次结构之间切换的正确方法是什么?
What is the correct way to switch between distinct UI hierarchies with SwiftUI?
想象一个典型的应用程序,其中包含入门、sign-in/registration 和某种内容。当应用程序加载时,您需要决定要显示哪个视图。天真的实现可能如下所示:
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
的不透明 return 类型。这可以通过使用 AnyView
包装器类型来缓解(虽然是 hackishly),它提供类型擦除并允许下面的代码编译。
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
中是否有功能可以处理到完全不同的视图层次结构的转换?
可能最 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()
}
}
想象一个典型的应用程序,其中包含入门、sign-in/registration 和某种内容。当应用程序加载时,您需要决定要显示哪个视图。天真的实现可能如下所示:
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
的不透明 return 类型。这可以通过使用 AnyView
包装器类型来缓解(虽然是 hackishly),它提供类型擦除并允许下面的代码编译。
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
中是否有功能可以处理到完全不同的视图层次结构的转换?
可能最 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()
}
}