使用@AppStorage路由用户时的导航错误

问题描述 投票:0回答:1

我遇到了一个有趣的行为(或者这可能是预期的行为,但我错了)。当我使用

@AppStorage
来将用户引导至入职或不入职时,第一个入职视图会显示两次。很难解释,这是一个gif:

单击“完成入门”后,我必须导航到 MainView,但第一个视图会以某种方式再次显示在中间。

仍然很难解释,所以这里是最基本的 SwiftUI 代码,你可以自己尝试一下:

import SwiftUI

@main
struct OnboardingApp: App {
    @AppStorage("onboardingCompleted") var onboardingCompleted = false
    
    var body: some Scene {
        WindowGroup {
            if !onboardingCompleted {
                FirstView()
            } else {
                MainView()
            }
        }
    }
}

struct FirstView: View {
    var body: some View {
        NavigationStack {
            VStack {
                Text("Welcome")
                
                NavigationLink("Second") {
                    SecondView()
                }
            }
            .onAppear {
                print("First View")
            }
        }
    }
}

struct SecondView: View {
    @AppStorage("onboardingCompleted") var onboardingCompleted = false
    
    var body: some View {
        VStack {
            Text("Onboarding complete")
            Button("Finish the onboarding") {
                onboardingCompleted = true
            }
        }
        .onAppear {
            print("Second View")
        }
    }
}

struct MainView: View {
    @AppStorage("onboardingCompleted") var onboardingCompleted = true
    
    var body: some View {
        NavigationStack {
            VStack {
                Text("Hello, Main View!")
                Button("Uncomplete onboarding") {
                    onboardingCompleted = false
                }
            }
            .onAppear {
                print("Main View")
            }
        }
    }
}

为什么

@AppStorage
var 更改后又显示了 FirstView?

swiftui
1个回答
0
投票

入职完成后,

onboardingCompleted
将为 true,因此您可以使用它来区分“正常”
onAppear
呼叫和移动到
MainView
时发生的意外呼叫。

@AppStorage("onboardingCompleted") var onboardingCompleted = false

...

.onAppear {
    if !onboardingCompleted {
        print("First View")
    }
}

或者,将

onAppear
移至
NavigationStack

有趣的是,这种行为在 macOS 上不会发生。

我的猜测(所以对此持保留态度)是 SwiftUI 使用

NavigationStack
实现
UINavigationController
,并将堆栈上的每个视图包装到自己的
UIHostingController
中,并且
onAppear
viewWillAppear 中被调用
。当移动到
MainView
时,由于某种原因
UINavigationController
会弹出到 root,因此
FirstView
onAppear
会被调用。

© www.soinside.com 2019 - 2024. All rights reserved.