层次结构之间切换的正确方法是什么

层次结构之间切换的正确方法是什么

本文介绍了使用 SwiftUI 在不同的 UI 层次结构之间切换的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

想象一个典型的应用程序,它具有入职、登录/注册和某种内容.当应用程序加载时,您需要决定显示哪个视图.一个简单的实现可能如下所示:

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 层次结构之间切换的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 03:57