ios SwiftUI|将路径追加到Routerpath onAppear后的奇怪行为

6tr1vspr  于 2023-06-07  发布在  iOS
关注(0)|答案(1)|浏览(122)

我想完全返工如何NavigationBar的外观和返工返回按钮,因为我喜欢,并有我自己的路由器在我的应用程序。
我创建这个示例项目是为了在开始我的项目之前了解NavigationStackNavigationPath是如何工作的(来自这个gist
一切都如预期的那样工作;直到我在onAppear阶段推出一些视图。
1.我隐藏了后退按钮,并添加了自己的,模仿默认的后退按钮。
1.我点击列表项目,应用程序按预期推送它们。
1.我的自定义后退按钮按预期删除它们。
现在,我添加了onAppear() {...},以便在应用运行时推送4个视图(试图模仿用户打开通知,应用将用户引导到相应的视图)
预期的行为是在navigationpath堆栈中有4个视图,我的自定义后退按钮将其删除。
但是应用程序的行为就像堆栈中没有视图一样,点击我的自定义后退按钮会使应用程序崩溃。(你会在app中看到screen count 0文本)我在onAppear中有print()语句,他们说我在堆栈中有4个视图。
如果我删除我的自定义后退按钮,并显示默认的后退按钮;是的,它工作,应用程序作为堆栈中的4个视图。(但应用程序内屏幕计数器仍将显示堆栈中的0视图)
这里是代码;用两种方法运行它来查看问题:
1.就这样跑吧。
1.注解掉.toolbar() { ... }.navigationBarBackButtonHidden()并运行
我不知道是我误解了这个概念,还是有一个bug。
顺便说一句; Xcode预览版的工作原理和我预期的一样。这是一个运行时问题。
谢谢你的时间。

import SwiftUI

final class Router: ObservableObject {
    @Published var path = NavigationPath()
}

struct ContentView: View {
    
    @StateObject var router: Router = Router()
    
    var body: some View {
        NavigationStack(path: $router.path) {
            RowListsView()
                .navigationDestination(for: Int.self) { i in
                    RowListsView()
                        .navigationBarBackButtonHidden()
                        .toolbar(content: {
                            if router.path.count > 0 {
                                ToolbarItem(placement: .navigationBarLeading) {
                                    Button("MyBack") {
                                        router.path.removeLast()
                                    }
                                }
                            }
                        })
                }
        }
        .environmentObject(router)
        .onAppear(perform: {
            print("before", router.path.count)
            router.path.append(1)
            router.path.append(2)
            router.path.append(3)
            router.path.append(4)
            print("after", router.path.count)
        })
    }
}

struct RowListsView : View{
    
    @EnvironmentObject var router: Router
    
    var body: some View {
        
        Form{
            List(1..<5, id: \.self) { i in
                NavigationLink(value: i) {
                    Text("\(i)")
                }
            }
            Section{

                    Button("Screen count \(router.path.count)"){
                        print("")
                    }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    
    static var previews: some View {
        ContentView()
    }
}
ubby3x7f

ubby3x7f1#

这是一个有趣的案例。我在Swift Playground中尝试了你的代码。当路径计数为0,我打后退按钮,应用程序崩溃了。在.onAppear中初始化@State或@StateObject对象不是正确/推荐的方法。

解决方案:

删除您的.onAppear {..}代码,应用程序将在没有后退按钮的情况下启动,并且运行正常。当你想要路径的初始值时,尝试不同的方法。例如,以下代码在Router类中使用简单的init。

工作编码:

当你点击后退按钮和路径计数到0,后退按钮将消失,这是正确的。

import SwiftUI

class Router: ObservableObject {
    @Published var path = NavigationPath()
    
    init() {
        self.path.append(1)
        self.path.append(2)
        self.path.append(3)
        self.path.append(4)
    }
}

struct ContentView: View {
    @StateObject var router: Router = Router()
    
    var body: some View {
        NavigationStack(path: $router.path) {
            RowListsView(router: router)
                .navigationDestination(for: Int.self) { i in
                    RowListsView(router: router)
                        .navigationBarBackButtonHidden()
                        .toolbar(content: {
                            if router.path.count > 0 {
                                ToolbarItem(placement: .navigationBarLeading) {
                                    Button("MyBack") {
                                        router.path.removeLast()
                                    }
                                }
                            }
                        })
                }
        }
        .environmentObject(router)
    }
}

struct RowListsView : View{
    @ObservedObject var router: Router
    
    var body: some View {
        Form{
            List(1..<5, id: \.self) { i in
                NavigationLink(value: i) {
                    Text("\(i)")
                }
            }
            Section{
                Button("Screen count \(router.path.count)"){
                    print("")
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

相关问题