[英]SwiftUI remove data into a structured array via a button in a ForEach
I'm trying to remove a line in my structured array when user click on the delete button.当用户单击删除按钮时,我试图删除结构化数组中的一行。 But as I use a foreach to load all my array lines into a specific subview I don't know how to pass the index of the ForEach into my subview to delete my line...
但是当我使用 foreach 将我所有的数组行加载到特定的子视图中时,我不知道如何将 ForEach 的索引传递到我的子视图中以删除我的行......
My code is like this,我的代码是这样的
ScrollView{
VStack {
ForEach(planeLibrary.testPlane){plane in
ZStack {
RoundedRectangle(cornerRadius: 16, style: .continuous)
.fill(Color.white)
.shadow(color: Color(Color.RGBColorSpace.sRGB, white: 0, opacity: 0.2), radius: 4)
PlaneCellView(plane: plane, planeLibrary: planeLibrary, line: ???)
}
}
}.padding(.horizontal, 16)
}
And my PlaneCellView:还有我的 PlaneCellView:
@State var plane: Plane
@ObservedObject var planeLibrary: PlaneLibrary
var line: Int
var body: some View {
//...
VStack(alignment: .leading) {
Text(plane.planeImat)
.font(.title)
.fontWeight(.bold)
Text(plane.planeType)
HStack{
Text(plane.isSe ? "SE" : "ME")
Text(plane.isNight ? "- Night" : "")
Text(plane.isIfr ? "- IFR" : "")
}
}
Spacer()
Button {
// HERE I don't know how to delete my array line ...
planeLibrary.testPlane.remove(at: line)
} label: {
Image(systemName: "trash.circle")
.foregroundColor(.red)
.font(.system(size: 30))
}
//...
}
My Plane library:我的飞机库:
struct Plane: Identifiable{
let id = UUID().uuidString
let planeImat: String
let planeType: String
let isSe: Bool
let isIfr: Bool
let isNight: Bool
let autoID: String
init (planeImat: String, planeType: String, isSe: Bool, isIfr: Bool, isNight: Bool, autoID: String){
self.planeType = planeType
self.planeImat = planeImat
self.isSe = isSe
self.isIfr = isIfr
self.isNight = isNight
self.autoID = autoID
}
init(config: NewPlaneConfig){
self.planeImat = config.imat
self.planeType = config.type
self.isSe = config.isSe
self.isIfr = config.isIfr
self.isNight = config.isNight
self.autoID = config.autoID
}
}
I've already try to add id: \.self
as I was able to find on this forum but without any success.我已经尝试添加
id: \.self
因为我能够在这个论坛上找到但没有成功。
You haven't actually included PlaneLibrary, so I will assume that planeLibrary.testPlane is an array of Plane structs.您实际上还没有包含 PlaneLibrary,所以我假设 planeLibrary.testPlane 是一个 Plane 结构数组。
There are many ways of solving this, including changing testPlane to be a Dictionary of Plane structs (indexed by id), or if order is important, in an OrderedDictionary (add the swift-collections
package to your project and import OrderedCollections
in the file where it is used).有很多方法可以解决这个问题,包括将 testPlane 更改为平面结构字典(由 id 索引),或者如果顺序很重要,则在 OrderedDictionary 中(将
swift-collections
package添加到您的项目并在文件中import OrderedCollections
它被使用)。 You could use testPlane.removeValue(at: id)
to remove the plane from either type of dictionary.您可以使用
testPlane.removeValue(at: id)
从任一类型的字典中删除平面。
If you keep it as an array, but your array might be large and you're worried about run-time efficiency, the best thing to do is to change your ForEach to include the index of the planes in the loop.如果您将它保存为一个数组,但您的数组可能很大并且您担心运行时效率,最好的办法是更改您的 ForEach 以在循环中包含平面的索引。
It would look something like this:它看起来像这样:
ForEach(Array(planeLibrary.testPlane.enumerated()), id: \.element.id) { index, plane in
// In this code you can use either plane, or index.
...
// UI code
Text(plane.autoID)
...
{ // remove closure
planeLibrary.testPlane.remove(at: index)
}
}
But if the array is of reasonable size, you could keep it as it is now and use testPlane.remove(where:)
to find it by id
at the time of deletion.但是如果数组的大小合理,你可以保持它现在的样子,并在删除时使用
testPlane.remove(where:)
通过id
找到它。 The code for this is much simpler and easier to read and understand, so it should probably be your first choice.这样做的代码更简单,更容易阅读和理解,因此它应该是您的首选。 Optimise for large lists later, if you need.
如果需要,稍后针对大型列表进行优化。
You can't pass the index in because that will crash the ForEach
View.您不能传入索引,因为这会使
ForEach
视图崩溃。 Instead, look up its index using its ID afterwards to remove it, eg相反,之后使用其 ID 查找其索引以将其删除,例如
class RecipeBox: ObservableObject {
@Published var allRecipes: [Recipe]
@Published var collections: [String]
...
func delete(_ recipe: Recipe) {
delete(recipe.id)
}
func delete(_ id: Recipe.ID) {
if let index = index(for: id) {
allRecipes.remove(at: index)
updateCollectionsIfNeeded()
}
}
...
func index(for id: Recipe.ID) -> Int? {
allRecipes.firstIndex(where: { $0.id == id })
}
...
This sample is from Defining the source of truth using a custom binding (Apple Developer)此示例来自使用自定义绑定定义真实来源(Apple Developer)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.