SwiftData 查询数组元素的排序顺序

问题描述 投票:0回答:1

我有一个简单的测试应用程序,其行为我只是不明白。

import SwiftUI
import SwiftData

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var items: [Item]

    var body: some View {
        NavigationView {
            List {
 //               ForEach(items) { item in
                ForEach(items.sorted(by: { $0.sortNr < $1.sortNr })) { item in
                    HStack{
                        Text("\(item.sortNr)")
                        Text("\(item.itemName)")
                    }
                }
                .onDelete(perform: deleteItems)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem {
                    Button(action: addItem) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
            }
        }
    }

    private func addItem() {
        withAnimation {
            let newItem1 = Item(itemName: "one", sortNr: 1)
            let newItem2 = Item(itemName: "two", sortNr: 2)
            let newItem3 = Item(itemName: "three", sortNr: 3)
            let newItem4 = Item(itemName: "four", sortNr: 4)
            modelContext.insert(newItem1)
            modelContext.insert(newItem2)
            modelContext.insert(newItem3)
            modelContext.insert(newItem4)
        }
    }

    private func deleteItems(offsets: IndexSet) {
        withAnimation {
            for index in offsets {
                modelContext.delete(items[index])
            }
        }
    }
}

@Model
final class Item {
    let id = UUID()
    var itemName : String
    var sortNr : Int
    
    init(itemName: String, sortNr: Int) {
        self.itemName = itemName
        self.sortNr = sortNr
    }
}

当我使用带注释的 ForEach 循环而不使用排序(by:..)时,项目列表会以某种随机顺序显示。删除项目会正确删除相应的选定项目。据我了解,如果未指定,Query 和 modelContext.insert 不保证特定顺序。

当我将 ForEach 循环与上面的排序(by..)一起使用时,项目将根据 sortNr 以排序方式显示。但是,当我滑动删除一项时,大多数情况下会删除“错误”的项目。偏移量是我选择的条目的正确索引,但似乎 [item] 在视图正文中与在 deleteItems 函数中具有不同的索引。

我需要在此 cod 中添加/更改什么才能在数组中拥有正确的索引。我可以使用 @Query(sort... 因为在我的应用程序中,列表视图的输入是动态参数。

arrays sorting swiftui swift-data
1个回答
0
投票

这根本不是 SwiftData 问题。您有一个数组,按一个顺序放入

ForEach
中,然后在
ForEach
中更改该顺序,因此该数组具有一个顺序,而
This really isn't a SwiftData issue at all. You have an array that you are putting into the 
ForEach
in one order, and then you are changing that order within the
ForEach` 具有另一个顺序。

例如,您有这些数组:

[2,3,1] 和 [2,3,1].sorted()。你其实有

[2,3,1] 和 [1,2,3]。 [2,3,1] 是你原来的,[1,2,3] 在

ForEach

因此,当用户在

ForEach
提供的视图中滑动删除“1”时,操作系统说好的,我们需要从数组中删除第一个元素,因此它会转到原始数组并删除第一个元素“2”。解决方案就是简单地对原始数组进行排序,然后将其提供给
ForEach
,这样您就可以将苹果与苹果进行比较。

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    // Sort the actual query
    @Query(sort: \Item.sortNr) private var items: [Item]

    var body: some View {
        NavigationView {
            List {
              ForEach(items) { item in
                // The rest of your code here
}               

如果您不允许删除,您的代码会没问题,但您引用的变量超出了

ForEach
中的范围,并且具有不同的规则集。

© www.soinside.com 2019 - 2024. All rights reserved.