Свойства @Binding не обновляются sh представление дочернего представления в SwiftUI - PullRequest
0 голосов
/ 05 января 2020

Я пытаюсь повторно использовать вид и добавляю его в 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

Superview имеет элементы управления, такие как Stepper, Slider, Picker, которые корректируют значения VStack (выравнивание, интервал и т. Д. c)

, и я хочу показать результат в зависимости от этих значений. но дочерний вид не изменился

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)
        }
    }
}

Я также ищу в Google, и они рекомендуют @EnviornmentObject. если это правильно, когда использовать оболочку свойства @Binding.

Разве это не свойства двусторонней привязки?

1 Ответ

1 голос
/ 05 января 2020

Проще говоря, вы можете использовать @Binding, когда вы хотите поделиться данными в двух местах.

@ Observable или @environmetobject должен использоваться, когда вы хотите поделиться своими данными в нескольких представлениях.

Ваш ForEach L oop в VStackView создает проблему, потому что Swiftui не делает знать, как он может идентифицировать каждый из ваших элементов уникальным образом, чтобы он не знал, как обновить их, когда значения изменяются.

Добавьте ваш код так:

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