将结构数组与结构数组中的字符串绑定

Binding Array of Structs with Strings in an Array of Structs

我是 Swift 的新手,所以我希望这不是什么傻事。我正在尝试构建一个结构数组,其中一个参数是另一个包含另一个结构的数组。我不确定是否有更好的方法,但我认为在尝试编辑嵌入式结构之前我已经取得了很好的进展。在它的简化形式中,它看起来像这样......

struct Group: Identifiable, Codable {
    var id = UUID()
    var name: String
    var number: Int
    var spaces: Bool
    var businesses: [Business]
}

struct Business: Identifiable, Codable {
    var id = UUID()
    var name: String
    var address: String
    var space: Int
    var enabled: Bool
    
}

这些在 class 中使用,带有存储在用户默认值中的 Observable 变量

class GroupSettings: ObservableObject {
    
    @Published var groups = [Group]() {
        didSet {
            UserDefaults.standard.set(try? PropertyListEncoder().encode(groups), forKey: "groups")
        }
    }

    init() {
        if let configData = UserDefaults.standard.value(forKey: "groups") as? Data {
           if let userDefaultConfig = try?
              PropertyListDecoder().decode(Array<Group>.self, from: configData){
                  groups = userDefaultConfig
              }
        }
     }
}

它已传递到我的初始视图,然后我想制作一个“编辑详细信息”屏幕。当它到达编辑详细信息屏幕时,我可以在文本显示中显示业务信息,但我无法使用 TextField,它抱怨无法将 a 转换为 Binding,但名称来自初始结构工作正常,类似的问题与 Int ...

我使用 @Binding 属性 ...

将一个组从第一个视图(其中包含组数组)传递到详细信息屏幕
@Binding var group: Group

var body: some View {

       TextField("", text: $group.name)     <---- WORKS

       List {
           ForEach(self.group.businesses){ business in
           
              if business.enabled {

                 Text(business.name)               <---- WORKS
                 TextField("", business.address)   <---- FAILS
                 TextField("", value: business.space, formatter: NumberFormatter())   <---- FAILS

              } else {

                 Text("\(business.name) is disabled"
              }
           }
       }
}

希望我已经很好地解释了自己,并且有人可以指出我的方法的错误。我确实尝试将第二个结构嵌入到第一个结构中,但这没有帮助。

提前致谢!

您可以在 ForEach 中使用 indices,然后仍然使用 $group 并通过这样的索引访问业务索引...

List {
    ForEach(group.businesses.indices) { index in
        TextField("", text: $group.businesses[index].address)
    }
}

另一种解决方案可能是使用 zip(或 )同时拥有企业及其指数:

struct TestView: View {
    @Binding var group: Group

    var body: some View {
        TextField("", text: $group.name)
        List {
            let items = Array(zip(group.businesses.indices, group.businesses))
            ForEach(items, id: \.1.id) { index, business in
                if business.enabled {
                    Text(business.name)
                    TextField("", text: $group.businesses[index].address)
                } else {
                    Text("\(business.name) is disabled")
                }
            }
        }
    }
}