SwiftUI:在子视图中的绑定只在导航回父视图时更新。

huangapple go评论53阅读模式
英文:

SwiftUI: Binding in child view only updates when navigating back to parent

问题

我有一个对象数组,通过父视图中的列表显示。每行都有一个导航链接到一个子视图,该视图传递给对象的绑定。子视图允许对所选项目进行基本编辑。子视图还包含一个按钮,该按钮显示一个表单,用户可以将所选对象“交换”到其中。

交换对象是可以的,但是只有在完全返回到父级后子视图才会更新。

我错过了一些东西,不允许子视图在关闭“交换列表”后更新吗?

当数据不是通过列表呈现时,我就没有这个问题。

这里有一些简化的示例... 在TestEditorView中,交换列表被按钮替换。

通过数组呈现的数据:

只有在返回到父级时,子视图才会更新

...

通过单个对象呈现的数据:

在不返回父级的情况下,子视图更新正确

英文:

I have an array of objects presented via a list in a parent view. Each row has a navigation link to a child view that is passed a binding to the object. The child view allows basic editing of the selected item. The child view also contains a button that presents a sheet to a default list of objects the user can "swap" the selected object to.

Swapping the object works, however the child view is only updated after navigating all the way back to the parent.

Am I missing something that is not allowing the child view to update after dismissing the "swap list"?

I do not have this issue when the data is not presented via a list.

Here are some trimmed down examples... The swap list is replaced with a button in the TestEditorView.

Data presented via array:

** child view does not update until navigating back to parent **

struct TestChildBindingList: View {
    @State private var text = ["This is some mutable text", "Please mutate", "Hopefully mutable text"]
    
    var body: some View {
        NavigationStack {
            VStack {
                List {
                    ForEach($text, id: \.self) { $item in
                        NavigationLink(item) {
                            TestChildView(text: $item)
                        }
                    }
                }
            }
            .navigationTitle("Parent View")
        }
    }
}

struct TestChildView: View {
    @Binding var text: String
    @State private var showingChangeText = false
    
    var body: some View {
        VStack {
            Text(text)
            
            Button("Change the text") {
                showingChangeText = true
            }
            .sheet(isPresented: $showingChangeText) {
                TestEditorView(text: $text)
            }
        }
        .navigationTitle("Child View")
    }
}

struct TestEditorView: View {
    @Environment(\.dismiss) var dismiss
    var text: Binding<String>?
    
    var body: some View {
        Button("Press here") {
            text?.wrappedValue = "I pressed the button"
            dismiss()
        }
    }
}

struct TestChildBindingList_Previews: PreviewProvider {
    static var previews: some View {
        TestChildBindingList()
    }
}

Data presented via single object:

** Child view updates correctly without navigating back to parent **

struct TestChildBindingItem: View {
    @State private var text = "This is definately mutable"
    @State private var showingChild = false
    
    var body: some View {
        NavigationStack {
            VStack {
                Text(text)
                
                Button("Show Child View") {
                    showingChild = true
                }
            }
            .sheet(isPresented: $showingChild) {
                TestChildItemView(text: $text)
            }
            .navigationTitle("Parent View")
        }
    }
}

struct TestChildItemView: View {
    @Binding var text: String
    @State private var showingChangeText = false
    
    var body: some View {
        VStack {
            Text(text)
            
            Button("Change the text") {
                showingChangeText = true
            }
            .sheet(isPresented: $showingChangeText) {
                TestEditorView(text: $text)
            }
        }
        .navigationTitle("Child View")
    }
}

struct TestEditorItemView: View {
    @Environment(\.dismiss) var dismiss
    var text: Binding<String>?
    
    var body: some View {
        Button("Press here") {
            text?.wrappedValue = "I pressed the button"
            dismiss()
        }
    }
}

struct TestChildBindingItem_Previews: PreviewProvider {
    static var previews: some View {
        TestChildBindingItem()
    }
}

Thank you for any help offered!

答案1

得分: 2

不使用

var text: Binding<String>?

Binding 是一个属性包装器,你必须以这种方式使用它。

@Binding var text: String

https://developer.apple.com/documentation/swiftui/binding

作为文字的 Binding 无法在需要时告知主体重新绘制。

英文:

Don’t use

var text: Binding<String>?

Binding is a property wrapper you have to use it that way.

@Binding var text: String

https://developer.apple.com/documentation/swiftui/binding

Binding as a literal is incapable of telling the body to redraw when needed.

huangapple
  • 本文由 发表于 2023年5月25日 04:42:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76327269.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定