我想完全返工如何NavigationBar的外观和返工返回按钮,因为我喜欢,并有我自己的路由器在我的应用程序。
我创建这个示例项目是为了在开始我的项目之前了解NavigationStack
和NavigationPath
是如何工作的(来自这个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()
}
}
1条答案
按热度按时间ubby3x7f1#
这是一个有趣的案例。我在Swift Playground中尝试了你的代码。当路径计数为0,我打后退按钮,应用程序崩溃了。在.onAppear中初始化@State或@StateObject对象不是正确/推荐的方法。
解决方案:
删除您的.onAppear {..}代码,应用程序将在没有后退按钮的情况下启动,并且运行正常。当你想要路径的初始值时,尝试不同的方法。例如,以下代码在Router类中使用简单的init。
工作编码:
当你点击后退按钮和路径计数到0,后退按钮将消失,这是正确的。