首页 > 解决方案 > @Binding 属性不是 SwiftUI 中子视图的刷新视图

问题描述

我正在尝试可重用视图并将其添加到 ContentView

这是我的孩子视图

struct VStackView: View {
    @Binding var spacing: Double
    @Binding var alignmentIndex: Int
    @Binding var elementsCount: Int

    private let alignments: [HorizontalAlignment] = [.leading, .center, .trailing]

    var body: some View {
        VStack(alignment: self.alignments[alignmentIndex], spacing: CGFloat(spacing)) {
            ForEach(0..<elementsCount) {
                Text("\($0)th View")
            }
        }
    }
}

这是超级视图

Superview 有 Stepper、Slider、Picker 等控件,可调整 VStack 的值(对齐、间距等)

我想根据该值显示结果。但子视图没有改变

struct LayoutView: View {
    private let layout: StackLayout

    @State private var spacing = 0.0
    @State private var alignmentIndex = 0
    @State private var alignment: HorizontalAlignment = .leading
    @State private var elementsCount: Int = 0

    private let alignmentsString = [".leading", ".center", ".trailing"]
    private let minValue = 0.0
    private let maxValue = 100.0

    init(_ layout: StackLayout) {
        self.layout = layout
    }

    var body: some View {
        NavigationView {
            Form {
                Section(header: Text("Controls")) {
                    VStack(alignment: .leading) {
                        Text("Spacing: \(Int(spacing))").font(.caption)

                        HStack {
                            Text("\(Int(minValue))")
                            Slider(value: $spacing, in: minValue...maxValue, step: 1)
                            Text("\(Int(maxValue))")
                        }

                        Divider()

                        Picker("alignment", selection: $alignmentIndex) {
                            ForEach(0..<self.alignmentsString.count) {
                                Text("\(self.alignmentsString[$0])")
                            }
                        }.pickerStyle(SegmentedPickerStyle())

                        Divider()

                        Stepper(value: $elementsCount, in: 0...10) {
                            Text("Element Count: \(elementsCount)")
                        }
                    }
                }

                VStackView(spacing: $spacing, alignmentIndex: $alignmentIndex, elementsCount: $elementsCount)
            }
            .navigationBarTitle(Text(layout.rawValue), displayMode: .inline)
        }
    }
}

我也搜索谷歌,他们推荐@EnviornmentObject。如果这是正确的,何时使用 @Binding 属性包装器。

不是双向绑定属性吗?

标签: iosswiftbindingswiftui

解决方案


简单地说,当您想在两个地方共享数据时,您可以使用@Binding。

当您想在多个视图中共享数据时,将使用 @Observable 或 @environmetobject。

VStackView 中的 ForEach 循环会产生问题,因为 Swiftui 不知道它如何唯一地识别您的每个项目,因此它不知道如何在值更改时更新它们。

像这样附加您的代码:

 ForEach(0..<elementsCount,  id: \.self) {
     Text("\($0)th View")
 }

推荐阅读