简体   繁体   English

SwiftUI NavigationView 在更新 observableObject 时弹回

[英]SwiftUI NavigationView pops back when updating observableObject

Background: I have been stuck on this annoying problem for days, trying different solution and searching stackoverflow etc for answers;背景:我被这个烦人的问题困扰了好几天,尝试不同的解决方案并搜索stackoverflow等来寻找答案; some have had similar problems but no suggested solution had the desired effect.有些人有类似的问题,但没有建议的解决方案达到预期的效果。

The problem is that when updating an observableObject or environmentObject down the navigation hierarchy view stack, the views get popped back to root.问题是当在导航层次视图堆栈中更新 observableObject 或 environmentObject 时,视图会弹出回根目录。 Viewing data from observableObject is fine, but not editing.从 observableObject 查看数据很好,但不能编辑。

Scenario is:场景是:

  1. I navigate to: root -> view1 -> view2.我导航到:root -> view1 -> view2。
  2. I update the environmentObject in View2 but then I get pushed back to: root -> view1我在 View2 中更新了 environmentObject 但随后又被推回到:root -> view1

I have simplified my app in order to make it more understandable.我简化了我的应用程序以使其更易于理解。 See below:见下文:

ObservableObject:可观察对象:

class DataStore: ObservableObject {
    static let shared = dataStore() 
    @Published var name   : String = ""
}

RootView:根视图:

struct ContentView: View {
   @StateObject var dataStore = DataStore.shared
   @State private var isShowingView1 = false
    var body: some View {
        NavigationView{
            VStack{
                Text(dataStore.name)
                NavigationLink(destination: View1(), isActive: $isShowingView1) { }
                Button(action: {
                    isShowingView1 = true
                })
            }
        }
    }
}

View1:视图1:

struct View1: View {
    @EnvironmentObject var dataStore: dataStore
    @State private var isShowingView2 = false
    var body: some View {
        ScrollView{
            VStack(alignment: .center) {
                Text(dataStore.name)
                NavigationLink(destination: View2(), isActive: $isShowingView2) { }
                Button(action: {
                    isShowingView2 = true
                }){
                    Text("Go to View2")
                }
            }
        }
    }
}

View2:视图2:

struct View2: View {
    @EnvironmentObject var dataStore: dataStore
    var body: some View {
        ScrollView{
            VStack(alignment: .center) {
                Text(dataStore.name)
                Button(action: {
                    dataStore.name = "updated value"
                }){
                    Text("Update data")
                }
                // When updating this environmentObject the viewstack will be pushed back to View1. If view2 had been navigated to view3 and the view3 had been updating the environmentObject, then it would also be pushed back to View1.
            }
        }
    }
}

Solution: I spent many hours searching for solutions and trying different approaches, but nothing I tried worked.解决方案:我花了很多时间寻找解决方案并尝试不同的方法,但我没有尝试过。 There seemed to be a few other people that had the same problem as I experienced, but the suggested solutions didn't cut it.似乎还有其他一些人遇到了与我相同的问题,但建议的解决方案并没有解决问题。 But then I stumbled on a solution for this problem when trying to implement another feature.但是后来我在尝试实现另一个功能时偶然发现了这个问题的解决方案。 So to be frank I am writing here now, not to ask this great community for help, but instead to give back to the community by providing the this solution to others that might need to see this.所以坦率地说,我现在写在这里,不是向这个伟大的社区寻求帮助,而是通过向可能需要看到这个的其他人提供这个解决方案来回馈社区。

The solution is really simple implement but was not so easy to come across.解决方案是非常简单的实现,但不是那么容易遇到。 If you experience a problem similar to me then you will only need to update your rootView accordingly:如果您遇到与我类似的问题,那么您只需要相应地更新您的 rootView:

RootView Updated:根视图更新:

struct ContentView: View {
   @StateObject var dataStore = DataStore.shared
   @State private var isShowingView1 = false
    var body: some View {
        NavigationView{
            VStack{
                Text(dataStore.name)
                NavigationLink(destination: View1(), isActive: $isShowingView1) { }
                Button(action: {
                    isShowingView1 = true
                })
            }
        }
        .navigationViewStyle(.stack)
        //ADD THIS LINE ABOVE
    }
}

This one line .navigationViewStyle(.stack) fixed the problem of popping the viewstack for me.这一行.navigationViewStyle(.stack)为我解决了弹出视图堆栈的问题。 Unfortunately I can't provide you with the logic explanation for this behaviour, but it works and I am satisfied with that.不幸的是,我无法为您提供这种行为的逻辑解释,但它有效,我对此感到满意。 Perhaps you are too, or perhaps you have insight on why this solution actually achieves the desired effect of allowing views down the hierarchy update observableObjects without being popped.也许你也是,或者也许你对为什么这个解决方案实际上达到了允许视图向下更新 observableObjects 而不被弹出的预期效果有所了解。

The solution is really simple implement but was not so easy to come across.该解决方案非常简单,但并不容易遇到。 If you experience a problem similar to me then you will only need to update your rootView accordingly:如果您遇到与我类似的问题,那么您只需要相应地更新您的 rootView:

RootView Updated: RootView 更新:

struct ContentView: View {
   @StateObject var dataStore = DataStore.shared
   @State private var isShowingView1 = false
    var body: some View {
        NavigationView{
            VStack{
                Text(dataStore.name)
                NavigationLink(destination: View1(), isActive: $isShowingView1) { }
                Button(action: {
                    isShowingView1 = true
                })
            }
        }
        .navigationViewStyle(.stack)
        //ADD THIS LINE ABOVE
    }
}

This one line .navigationViewStyle(.stack) fixed the problem of popping the viewstack for me.这一行 .navigationViewStyle(.stack) 为我解决了弹出视图堆栈的问题。 Unfortunately I can't provide you with the logic explanation for this behaviour, but it works and I am satisfied with that.不幸的是,我无法为您提供这种行为的逻辑解释,但它有效,我对此感到满意。

NavigationView still has this strange behavior. NavigationView仍然有这种奇怪的行为。

However, NavigationStack seems to have fixed this issue.然而, NavigationStack似乎已经解决了这个问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 SwiftUI NavigationView 自行弹出 - SwiftUI NavigationView pops by itself SwiftUI NavigationLink push in onAppear 使用@ObservableObject 时立即弹出视图 - SwiftUI NavigationLink push in onAppear immediately pops the view when using @ObservableObject SwiftUI 通过 Navigationview 推送视图在关闭工作表后弹出 - SwiftUI pushed View through Navigationview pops back after dismissing sheet SwiftUI TabView 内的 NavigationView 从堆栈中的任何视图弹出回 Root - SwiftUI NavigationView inside TabView pops back to Root, from any view in the stack SwiftUI:当先前的视图列表更改时,NavigationView 详细视图会弹出回栈 - SwiftUI: NavigationView detail view pops backstack when previous's view List changes NavigationView 弹回 root,省略中间视图 - NavigationView pops back to root, omitting intermediate view SwiftUI:按下 NavigationView 的后退按钮时执行代码 - SwiftUI: Execute code when back button for NavigationView is pressed SwiftUI 视图未通过绑定到 ObservableObject 上的计算属性进行更新 - SwiftUI View not updating with binding to computed property on ObservableObject 当 ObservableObject 的所有属性都更新时,SwiftUI 会收到通知 - SwiftUI be notified when all properties of an ObservableObject are updated 在SwiftUI中继承ObservableObject时不会触发视图刷新 - View refreshing not triggered when ObservableObject is inherited in SwiftUI
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM