【问题标题】:Is @Binding possible in a ForEach list using list's id?使用列表的 id 在 ForEach 列表中是否可以使用 @Binding?
【发布时间】:2019-11-23 07:33:12
【问题描述】:

在 ParentView 中使用 @State 和在 ChildView 中使用 @Binding,我们可以在打印视图和子视图中的 2 个变量的值之间建立联系。使用这样的代码:

ChildView(valueFromParent: $valueInParent)

在 ParentView 中使用 @State 拥有 valueInParent,在 ChildView 中使用 @Binding 拥有 valueFromParent。这样,这两个变量现在是相关的,改变一个会改变另一个。

是否可以在 ForEach 循环中使用行的 ID 号在两个视图之间进行这种绑定?像这样的:

ForEach((1...15), id: \.self) {item in
    ChildView(valueFromParent[item]: self.$valueInParent[item])
}

我知道另一种方法 - 创建一个项目数组以传递给具有数组内 ID 的列表:

@State private var list = [
        (id: 0, model: ListItemModel()),
        (id: 1, model: ListItemModel()),
        (id: 2, model: ListItemModel()),
        (id: 3, model: ListItemModel()),
        (id: 4, model: ListItemModel())
    ]

编辑:但我希望避免使用上述带有固定项目列表的数组。

我想使用这样的 ForEach 循环创建一个简单的原型:ForEach((1...15), id: .self)。问题是我不知道如何从列表中的特定行访问 var 的值。

【问题讨论】:

  • 这是可能的,但如果它真的是你需要的,请三思而后行,因为ForEach(range) 是常量容器,即。您将无法更改其大小,即。由于超出范围异常,在模型容器中添加/删除项目要么无效(添加时)或崩溃(删除时)。
  • 感谢您告诉我这些限制。是的,这仍然是我需要的。它用于原型制作目的。快速创建列表并更改行内的内容。它不是用于生产

标签: xcode swiftui swiftui-list


【解决方案1】:

这是一个可能的方法的演示模块。希望对您有所帮助。

更新:提供了两种变体 - 带有模型的数组和带有模型的字典

1.以数组作为模型容器的变体

import SwiftUI

struct Model {
    var name: String
    var value: Int

    init(_ name: String, _ value: Int) {
        self.name = name
        self.value = value
    }
}

struct DetailsView : View {
    @Binding var item: Model
    var body: some View {
        HStack {
            Text("Name")
            TextField("", text: $item.name)
        }
    }
}

struct Main: View {
    @State var models = [Model("A", 1), Model("B", 2), Model("C", 3), Model("D", 4)]

    var body: some View {
        NavigationView {
            List {
                ForEach(0..<models.count) { i in
                    NavigationLink(destination: DetailsView(item: self.$models[i])) {
                        Text("Model: \(self.models[i].name)")
                    }
                }
            }
        }
    }
}
struct DemoMainDetailByID: View {
    var body: some View {
        Main()
    }
}

struct DemoMainDetailByID_Previews: PreviewProvider {
    static var previews: some View {
        DemoMainDetailByID()
    }
}

2.以字典作为模型容器的变体

struct Main: View {
    @State var models: [Int: Model] = [1: Model("A", 1), 2: Model("B", 2), 3: Model("C", 3), 4: Model("D", 4)]

    var body: some View {
        NavigationView {
            List {
                ForEach(1...4, id: \.self) { i in
                    NavigationLink(destination: DetailsView(item: Binding(self.$models[i])!)) {
                        Text("Model: \(self.models[i]!.name)")
                    }
                }
            }
        }
    }
}

【讨论】:

  • 谢谢,但实际上我想将 id 作为可数数。例如:ForEach((1...15), id: \.self)。并且不要使用数组。拥有数组,从 3 行更改为 30 行比使用 (1...15) 更耗时。如果我使用可数数,\(self.models[i].name) 的等价物是多少?我希望在 ForEach 列表中使用 @Binding 我可以访问第 9 行中的 var valueFromParent。使用类似这样的东西: valueFromParent[9]
  • 你的意思是字典作为模型的容器吗?
  • 不知道我的回答对不对。我是编码新手;)我的意思是 - 根本没有模型。
  • 只是一个带有定义行的 ChildView 的 ForEach 列表。在这一行中,一个可点击的 Star 会改变一个值:喜欢与否。对或错。但我想访问 ParentView 中的每一行并检查:第 3 行是否最喜欢?并根据值在列表之外显示不同的文本: Text(item[3].valueFromParent ? "On" : "Off") 在类似的问题中,您建议使用 ObservableObject。我想让事情变得更简单(如果可能的话)并在 ForEach 中使用 @Binding。我只在 2 个视图之间传递值。
  • 谢谢,你的第二个例子几乎就是我想要实现的。但是@State var 模型可以更简单吗?就像一个空数组。或 1 个元素数组。因为里面有4个项目。如果我将 ForEach(1...4 更改为 ForEach(1...40) 会发生什么?
猜你喜欢
  • 2015-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-11
  • 2014-09-03
  • 1970-01-01
  • 1970-01-01
  • 2017-01-09
相关资源
最近更新 更多