【问题标题】:NavigationLink's destination view doesn't update when variables changeNavigationLink 的目标视图在变量更改时不会更新
【发布时间】:2021-01-16 21:20:11
【问题描述】:

我在 SwiftUI 中遇到了奇怪的行为,我不确定这是一个错误(我正在运行 Big Sur 和 XCode 12 测试版)还是我做错了。

当我将变量传递给NavigationLink 的目标视图时,该目标视图不会在变量更改时重新呈现。我已经隔离了这种行为以向您展示。这是一个完整的示例(仅适用于新的 SwiftUI 版本和 iOS 14):

import SwiftUI

struct ContentView: View {
    
    @State var name: String
    
    var body: some View {
        
        NavigationView {
            List {
                
                NavigationLink(destination: MasterView(name: name)) {
                    Text("Show Name In Big")
                }
                
                Rectangle()
                    .frame(height: 1)
                
                Text("Current Name: \(name)")
                    .font(.headline)
                    .foregroundColor(.accentColor)
                
                Button(action: {
                    name = "Doug"
                }, label: {
                    Text("Change Name")
                        .bold()
                })
            }
            .listStyle(SidebarListStyle())
            
            Text("Master")
            Text("Detail")
        }
        
    }
}

struct MasterView: View {
    let name: String
    var body: some View {
        Text(name)
            .font(.title)
    }
}

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

这是一个演示行为的简短 gif(抱歉分辨率不好,这是一个分辨率更好的视频:https://www.youtube.com/watch?v=aTCex86tkYQ):

这是预期的行为吗?

编辑:

一个简单的示例来证明您不需要 Binding 来在值更改时重新呈现视图:

import SwiftUI

struct TestView: View {
    
    @State var someVariable: String = "Old Value"
    
    var body: some View {
        VStack {
            Text(someVariable)
            SubView(someVariable: someVariable) // initialized without Binding
            
            Button("Click to update variable") {
                someVariable = "New Value"
            }
        }
    }
}

struct SubView: View {
    
    let someVariable: String
    
    var body: some View {
        Text(someVariable)
    }
}

struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        TestView()
    }
}

谢谢!

【问题讨论】:

    标签: swift swiftui


    【解决方案1】:

    @Binding 用于name 中的MasterView

    @Binding var name : String
    

    并且,通过name 喜欢:

    NavigationLink(destination: MasterView(name: $name)) {
    ...
    }
    

    现在,当您的state(name) 更改时,其他视图(使用该状态为Binding)将收到通知。

    【讨论】:

    • 对不起,如果我弄错了,但如果没有@Binding,它不应该也能工作吗?我不需要能够在MasterView 中更改name,因此@Binding 不合适(遵循Apple 的最佳实践)。如果我在我的侧边栏列表中添加MasterView(name: name)(只需将其添加到 NavigationLink 下方左右),那么即使没有@Binding,当变量更改时视图也会正常更新
    • 我不明白为什么要在没有属性包装器的情况下更新视图。也许有一些我不知道的概念。
    • @Quantm 提供的答案是绝对正确的。 SwiftUI 中的 NavigationLink 是指向视图的非惰性链接。因此,即使您实际上没有单击链接,也会运行 init 方法。因此,它的工作方式与您描述的情况不同。
    • @Binding 只是让您可以写回某些父视图的原始变量。即使没有它,SwiftUI 也会重新渲染使用已更改变量的子视图。
    • @Quantm 绑定不仅用于写回原始变量。它还用于通知自己的视图重新渲染自己。如果您需要视图而不更改变量并重新渲染视图,您的解决方案是什么?
    【解决方案2】:

    我很确定这是 SwiftUI 中 List 的错误。如果您在代码中将List 替换为VStack,它应该可以正常工作。我还没有想出一个解决方法。如果您在错误报告文件中收到 Apple 的回复,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-04-10
      • 1970-01-01
      • 1970-01-01
      • 2019-06-02
      • 2016-08-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多