【问题标题】:SwiftUI Bind to @ObservableObject in arraySwiftUI 绑定到数组中的@ObservableObject
【发布时间】:2022-11-20 06:42:04
【问题描述】:

如何将可绑定对象传递到 ForEach 循环内的视图中?

下面的最小可重现代码。

class Person: Identifiable, ObservableObject {
    let id: UUID = UUID()
    @Published var healthy: Bool = true
}


class GroupOfPeople {
    let people: [Person] = [Person(), Person(), Person()]
}

public struct GroupListView: View {
    
    //MARK: Environment and StateObject properties
    
    //MARK: State and Binding properties
    
    //MARK: Other properties
    let group: GroupOfPeople = GroupOfPeople()
    
    //MARK: Body
    public var body: some View {
        ForEach(group.people) { person in
            //ERROR: Cannot find '$person' in scope
            PersonView(person: $person)
        }
    }
    
    //MARK: Init
    
}

public struct PersonView: View {
    
    //MARK: Environment and StateObject properties
    
    //MARK: State and Binding properties
    @Binding var person: Person
    //MARK: Other properties
    
    
    //MARK: Body
    public var body: some View {
        switch person.healthy {
        case true:
            Text("Healthy")
        case false:
            Text("Not Healthy")
        }
    }
    
    //MARK: Init
    init(person: Binding<Person>) {
        self._person = person
    }
}

我得到的错误是Cannot find '$person' in scope。我知道在执行 ForEach 循环时,变量的 @Binding 部分不在范围内。我正在寻找关于不同模式的建议,以完成 @Binding 对象到 SwiftUI 列表中的视图。

【问题讨论】:

  • 您的示例中没有任何内容要求您将绑定传递给您的PersonView,因此简单的答案就是删除@Binding 并传递person。更复杂的答案可能是您需要考虑您的模型对象。您可能需要的不仅仅是一个简单的数组,但您还没有解释为什么思考你需要一个绑定

标签: ios arrays swift swiftui observableobject


【解决方案1】:

SwiftUI 的方式是这样的:

// struct instead of class
struct Person: Identifiable {
    let id: UUID = UUID()
    var healthy: Bool = true
}


// class publishing an array of Person
class GroupOfPeople: ObservableObject {
    @Published var people: [Person] = [
        Person(), Person(), Person()
    ]
}

struct GroupListView: View {
    
    // instantiating the class
    @StateObject var group: GroupOfPeople = GroupOfPeople()
    
    var body: some View {
        List {
            // now you can use the $ init of ForEach
            ForEach($group.people) { $person in
                PersonView(person: $person)
            }
        }
    }
}

struct PersonView: View {
    
    @Binding var person: Person

    var body: some View {
        HStack {
            // ternary instead of switch
            Text(person.healthy ? "Healthy" : "Not Healthy")
            Spacer()
            // Button to change, so Binding makes some sense :)
            Button("change") {
                person.healthy.toggle()
            }
        }
    }
}

【讨论】:

    【解决方案2】:

    你不需要Binding。你需要ObservedObject

    【讨论】:

      【解决方案3】:

      对于仍然想知道的人......看起来已经添加了

      .onContinuousHover(perform: { phase in
          switch phase {
          case .active(let location):
              print(location.x)
          case .ended:
              print("ended")
          }
      })
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-01-25
        • 2020-02-14
        • 1970-01-01
        • 2019-12-10
        • 2021-07-06
        • 1970-01-01
        • 1970-01-01
        • 2020-09-13
        相关资源
        最近更新 更多