首页 > 解决方案 > 在 SwiftUI 中使用`@Binding` 初始化`@State`ful 结构

问题描述

我有一个应用程序,其中两个不同的结构依赖于单独的数据,当我更改该数据时,两个结构都需要了解更改。我想我可以通过重构或使用 来解决问题@EnvironmentObject,但我想了解为什么这段代码不起作用。在SceneDelegate.swiftiOS 项目中,设置contentViewwithlet contentView = StateTestTopView()然后使用以下代码创建文件:

import SwiftUI

struct Person { @Binding var name: String }
struct Character { @Binding var name: String }

struct StateTestTopView: View {
  @State private var name: String = "Bilbo"

  var body: some View {
    VStack {
      StateTestPickerView(name: $name)
      Spacer()
      Text("Global name selection is \(name)").font(.title)
    }
  }
}

struct StateTestPickerView: View {
  @Binding var name: String
  @State private var person: Person
  @State private var character: Character
  init(name: Binding<String>) {
    self._name = name
    self._person = State(initialValue: Person(name: name))
    self._character = State(initialValue: Character(name: name))
  }
  var body: some View {
    VStack{
      Picker(selection: $name,
             label: Text(verbatim: "Selected name: \(name)")) {
              ForEach(["Sam", "Gandalf", "Gollum"], id: \.self) { name in
                Text(name)
              }
      }
      Text("You picked \(name)")
      ShowPersonAndCharacter(
        person: self.$person, character: self.$character)
    }
  }
}

struct ShowPersonAndCharacter: View {
  @Binding var person: Person
  @Binding var character: Character

  var body: some View {
    Text("\(person.name) is great! \(character.name) is the same person!")
  }
}

问题是 and 结构的has ,ShowPersonAndCharacter但是当底层数据发生变化时,绑定的结构不会更新。我怀疑问题出在 Picker 视图初始化程序中:@BindingPersonCharacter

  @Binding var name: String
  @State private var person: Person
  @State private var character: Character
  init(name: Binding<String>) {
    self._name = name
    self._person = State(initialValue: Person(name: name))
    self._character = State(initialValue: Character(name: name))
  }

在这里,我认为PersonandCharacter结构是使用绑定 String 的快照创建的,实际上并没有得到绑定。我不确定如何解决这个问题,或者即使我的诊断是远程正确的。

有任何想法吗?

谢谢你的时间!

标签: swiftswiftui

解决方案


我同意@Asperi,绑定旨在用于视图而不是模型。事实上,在这种情况下,您根本不需要模型进行绑定。由于它@Binding var name: String是一个绑定,StateTestPickerView因此它会在更新后立即自行更新视图。请参阅以下代码修改。这对我来说非常好:

struct Person { var name: String }
struct Character { var name: String }

struct StateTestTopView: View {
    @State private var name: String = "Bilbo"

    var body: some View {
        VStack {
            StateTestPickerView(name: $name)
            Spacer()
            Text("Global name selection is \(name)").font(.title)
        }
    }
}

struct StateTestPickerView: View {
    @Binding var name: String

    var body: some View {
        VStack{
            Picker(selection: $name,
                   label: Text(verbatim: "Selected name: \(name)")) {
                    ForEach(["Sam", "Gandalf", "Gollum"], id: \.self) { name in
                        Text(name)
                    }
            }
            Text("You picked \(name)")
            ShowPersonAndCharacter(person: Person(name: self.name),
                                   character: Character(name: self.name))
        }
    }
}

struct ShowPersonAndCharacter: View {
    var person: Person
    var character: Character

    var body: some View {
        Text("\(person.name) is great! \(character.name) is the same person!")
    }
}

请注意,绑定属性包装器已从模型中删除。此外,StateTestPickerView在以下代码中使用名称绑定直接调用视图:ShowPersonAndCharacter(person: Person(name: self.name), character: Character(name: self.name))


推荐阅读