ios - 如何使用 ForEach 中制作的 TextField 更新结构的属性
问题描述
在 SwiftUI 中,我有一个菜单项列表,每个菜单项都有名称、价格等。有一堆类别,每个类别下都有一个项目列表。
struct ItemList: Identifiable, Codable {
var id: Int
var name: String
var picture: String
var list: [Item]
@State var newItemName: String
}
我正在寻找一种在每个类别中创建一个 TextField 的方法,该类别将添加到其项目数组中。
通过 ForEach 循环制作 TextField 非常简单,但我在尝试使用输入的文本将新项目添加到正确的类别时遇到了困难。
ForEach(menu.indices) { i in
Section(header: Text(menu[i].name)) {
ForEach(menu[i].list) { item in
Text(item.name)
}
TextField("New Type:", text: /*some kind of bindable here?*/) {
menu[i].list.append(Item(name: /*the text entered above*/))
}
}
}
我考虑过像其他问题一样使用@Published 和 Observable Object ,但我需要 ItemList 是一个 Codable 结构,所以我无法弄清楚如何将答案放在我的案例中。
TextField("New Type:", text: menu[i].$newItemName)
无论如何,任何想法将不胜感激,谢谢!
解决方案
你只需要专注于你的View
.
import SwiftUI
struct ExpandingMenuView: View {
@State var menu: [ItemList] = [
ItemList(name: "Milk Tea", picture: "", list: [ItemModel(name: "Classic Milk Tea"), ItemModel(name: "Taro milk tea")]),
ItemList(name: "Tea", picture: "", list: [ItemModel(name: "Black Tea"), ItemModel(name: "Green tea")]),
ItemList(name: "Coffee", picture: "", list: [])
]
var body: some View {
List{
//This particular setup is for iOS15+
ForEach($menu) { $itemList in
ItemListView(itemList: $itemList)
}
}
}
}
struct ItemListView: View {
@Binding var itemList: ItemList
@State var newItemName: String = ""
var body: some View {
Section(header: Text(itemList.name)) {
ForEach(itemList.list) { item in
Text(item.name)
}
TextField("New Type:", text: $newItemName, onCommit: {
//When the user commits add to array and clear the new item variable
itemList.list.append(ItemModel(name: newItemName))
newItemName = ""
})
}
}
}
struct ItemList: Identifiable, Codable {
var id: UUID = UUID()
var name: String
var picture: String
var list: [ItemModel]
//@State is ONLY for SwiftUI Views
//@State var newItemName: String
}
struct ItemModel: Identifiable, Codable {
var id: UUID = UUID()
var name: String
}
struct ExpandingMenuView_Previews: PreviewProvider {
static var previews: some View {
ExpandingMenuView()
}
}
如果您不使用 Xcode 13 和 iOS 15+,那么 SO 中有许多解决方案用于与数组元素绑定。以下只是其中之一
ForEach(menu) { itemList in
let proxy = Binding(get: {itemList}, set: { new in
let idx = menu.firstIndex(where: {
$0.id == itemList.id
})!
menu[idx] = new
})
ItemListView(itemList: proxy)
}
另请注意,使用indices
被认为是不安全的。您可以观看 WWDC2021 的 Demystifying SwiftUI 了解更多详情。
推荐阅读
- php - 如何将提交的变量放入函数中
- python - 为什么在 Django models.Manager 中定义 create_foo() 而不是覆盖 create()?
- python - Python3 - 拆分字符串并仅保留结尾部分
- elasticsearch - 日期模式在 logstash 中无法按预期工作
- django-models - 自定义中间表 django 获取记录
- java - 用于自动确定哪些单元测试可能受源更改影响的 Eclipse 工具
- xcode - coreml 推理结果与 cpu 和 gpu 不同
- mongodb - MongoDB + Express 如何优化代码?
- java - RatingBar 中的星数看起来错误
- node.js - 如何将 webpack env 传递给 nodejs 应用程序?