【问题标题】:SwiftUI updating @Binding value in NavigationLink(destination:label) causes destination to reappearSwiftUI 更新 NavigationLink(destination:label) 中的 @Binding 值导致目的地重新出现
【发布时间】:2021-02-22 01:04:44
【问题描述】:

我有一个奇怪的问题,我导航到EditView 并从ContentView 编辑状态变量。之后我用presentation.wrappedValue.dismiss() 解雇EditView。问题是,一旦视图被关闭,它就会再次出现。

我使用的是 XCode 12.4,我的 iOS 部署目标设置为 14.4

观察:

  • 如果未编辑值,EditView 不会重新出现
  • 从 ContentView 树中删除更改后的值 Text("Value: \(title)") >> Text("Value") 可以解决问题,但这显然不是解决方案。
  • 将NavigationLink 从.toolbar 移出,例如
    VStack {
        Text("Value: \(title)")
        NavigationLink(destination: EditView(title: $title)){
            Text("Edit")
        }
    }

也解决了这个问题,但这似乎是一个 hack。此外,我想继续使用.toolbar,因为我喜欢.navigationTitle 动画,如果我有一个没有工具栏的导航标题,我就不能在屏幕右上角有一个按钮。

这是完整的代码:

    import SwiftUI

    struct ContentView: View {
        @State var title: String = "Title"
        @State var isActive: Bool = false
        
        var body: some View {
            NavigationView {
                    
                Text("Value: \(title)")
                    .toolbar {
                        ToolbarItem(placement: .navigationBarTrailing) {
                            NavigationLink(destination: EditView(title: $title, isActive: $isActive), isActive: $isActive){
                                Text("Edit")
                            }
                        }
                    }
            }
        }
    }
    
    struct EditView: View {
        @Environment(\.presentationMode) var presentation
        
        @Binding var title: String
        @Binding var isActive: Bool
        
        var body: some View {
            Button(action: {
                title = "\(Date().timeIntervalSince1970)"
    //            presentation.wrappedValue.dismiss()
                isActive = false
            }){
                Text("Done")
            }
        }
    }
    
    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }

据我所知,这是一个 .toolbar 错误,如果结果是这样,我会将其报告给 Apple,但与此同时,是否有人对此有更好的解决方案和/或解释?

干杯!

编辑:

我用isActive 的值更新了代码NavigationLink。当这样写时它不起作用,但是取消注释注释掉的行使它起作用。但这很 hacky。

【问题讨论】:

    标签: binding swiftui swiftui-navigationlink


    【解决方案1】:

    您正在混淆 2 件事 NavigationLink 将在 stack 上推送视图,就像在 swift 中的 NavigationController 一样。这就是为什么您可以在导航到第二个视图后看到返回按钮。当您点击返回按钮时,它将弹出stack 中最顶部的视图。不需要presentationMode,关闭呈现的视图不会将其弹出堆栈。

    要呈现一个视图并关闭它,您可以查看下面的代码。

    import SwiftUI
    
    struct ContentViewsss: View {
        @State var title: String = "Title"
        @State var isPresented = false
        
        var body: some View {
            NavigationView {
                Text("Value: \(title)")
                    .toolbar {
                        ToolbarItem(placement: .navigationBarTrailing) {
                            Button(action: {
                                isPresented.toggle()
                            }){
                                Text("Edit")
                            }
                        }
                    }
            }.sheet(isPresented: $isPresented, content: {
                EditView(title: $title, state: $isPresented)
            })
        }
    }
    
    struct EditView: View {
       
        @Binding var title: String
        @Binding var state: Bool
        
        var body: some View {
            Button(action: {
                title = "\(Date().timeIntervalSince1970)"
                state.toggle()
            }){
                Text("Done")
            }
        }
    }
    

    如果您想要NavigationLink 功能,您可以从第二个视图中删除presentationMode 代码,并保持ContentView 原样-:

    struct EditView: View {
         //@Environment(\.presentationMode) var presentation
        
        @Binding var title: String
          
        var body: some View {
            Button(action: {
                title = "\(Date().timeIntervalSince1970)"
                // presentation.wrappedValue.dismiss()
            }){
                Text("Done")
            }
        }
    }
    

    【讨论】:

    • 问题是,我需要以编程方式关闭视图 - 当我按下“完成”按钮时,afaik 演示模式是唯一的方法?
    • @EliseyOzerov 没有得到你。如果您不想使用presentationMode 关闭,您也可以将isPresented state 属性作为绑定传递给EditView,并在完成按钮上将其切换回false。
    • 我刚刚尝试过,但没有任何反应。有趣的是,如果我同时尝试两者,它会起作用。但这是一个 hacky 解决方案,哈哈
    • @EliseyOzerov 你能用你试过的更新你的代码吗?
    • 我不能在那里使用工作表修饰符,因为 ContentView 中的代码已经在我项目的工作表中 - 我更新了代码顺便说一句
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-23
    • 1970-01-01
    • 2020-04-05
    • 2021-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多