问题描述
想象一个典型的应用程序,它具有入职、登录/注册和某种内容.当应用程序加载时,您需要决定显示哪个视图.一个简单的实现可能如下所示:
Imagine a typical app that has onboarding, sign-in/registration, and content of some kind. When the app loads you need to make some decision about which view to show. A naive implementation may look like this:
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
包装器类型来缓解(尽管有点笨拙),它提供类型擦除并允许编译下面的代码.
Obviously this approach fails because SwiftUI views require an opaque return type of some View
. This can be mitigated (albeit hackishly) using the AnyView
wrapper type, which provides type erasure and will allow the code below to compile.
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
中是否有可以处理到完全不同的视图层次结构的转换的功能?
Is there a more correct way of doing this that doesn't require the use of AnyView
? Is there functionality in the SceneDelegate
that can handle the transition to a completely distinct view hierarchy?
推荐答案
可能最 SwiftUI
-y 的方法是使用 Group
视图:
Probably the most SwiftUI
-y way to do things like these is by using the Group
view:
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
的类型擦除(如果不是绝对必要的话,可以避免).
The most important thing to note is that, this way, you won't rely on type erasure with AnyView
(to avoid if not strictly necessary).
如果要将初始视图创建封装在方法中,请不要使用类型擦除.相反,使用 some
关键字:
If you want to encapsulate the initial view creation in a method don't use type erasure. Instead, use the some
keyword:
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()
}
}
这篇关于使用 SwiftUI 在不同的 UI 层次结构之间切换的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!