【问题标题】:Binding Array of Structs with Strings in an Array of Structs将结构数组与结构数组中的字符串绑定
【发布时间】:2021-01-23 20:36:08
【问题描述】:

我是 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 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 转换为绑定,但名称来自初始结构工作正常,与 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"
              }
           }
       }
}

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

提前致谢!

【问题讨论】:

  • 尝试阅读stackoverflow.com/questions/63839270/…,它向您展示了如何使用数组创建绑定。我可以看到 business.address 不是绑定变量
  • @NotAPhoenix 我查看了您发布的链接,但正如我在问题中所说,我是 Swift 新手,我很难理解该链接如何帮助我的用例。没有任何嵌入式结构数组,我无法理解如何将该解决方案应用于我的问题。如果您有时间,您可以添加一个带有更多上下文或一些指针的答案,以帮助我朝着正确的方向前进。

标签: swift string struct binding swiftui


【解决方案1】:

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

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

【讨论】:

  • 您好,感谢您的回答,它对 TextField 非常有用,但是,它破坏了 Text 选项,然后显示“Initializer 'init(_:)' 要求 'Binding' 符合 ' StringProtocol'' ,当我尝试使用 business[index].enabled 时,我再次得到'无法将 转换为 Binding'。
  • 我已经用 Bool 用例更新了问题。
  • @Plasma 您需要使用group.businesses[index],例如:Text("\(group.businesses[index].name) is disabled")if group.businesses[index].enabled { ... }
  • @pawello2222 谢谢,看起来这样做已经解决了我的大部分问题,但是这似乎是一种非常冗长的方法。我认为 Swift 只是为了简化语法。 :'(
【解决方案2】:

另一种解决方案可能是使用zip(或enumerated)同时拥有业务及其索引:

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

【讨论】:

  • 所以我混合使用了这两个答案,使用@davidev .indices 解决方案,然后在 ForEach 中执行 let business = group.businesses[index]。我可以为 TextFields 使用长手 $group.businesses[index].address 为其他人使用较短的 business.enabled。它仍然没有我想要的那么漂亮,但它确实有效,这是主要的。谢谢两位的回答!
猜你喜欢
  • 2013-07-29
  • 1970-01-01
  • 2021-03-30
  • 2017-06-12
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2011-08-04
  • 2014-09-28
相关资源
最近更新 更多