如何使用.reversed()处理SwiftUI列表数组的.onDelete



我正在尝试制作一个基本的SwiftUI列表,其中每个新的列表项都显示在列表的顶部。为此,我将.reversed((附加到传递到ForEach循环的数组中,用viewModel.itemList表示。我还设置了.onDelete来处理列表项的删除。但是,当我删除一个项目时,例如列表中的最后一个项目,它会删除数组中的最后项目(列表顶部的项目(。当数组反转时,如何配置.onDelete来删除正确的项?

请参阅下面的代码。谢谢

ContentView

struct ContentView: View {

@StateObject var viewModel = ToDoListViewModel()
@State private var listItemName = ""

var body: some View {
NavigationView {
VStack(alignment: .leading) {
List {
ForEach(viewModel.itemList.reversed()) { item in
Text(item.listItem)
}.onDelete { index in
self.viewModel.itemList.remove(atOffsets: index)
}
}

HStack {
TextField("Enter List Item", text: $listItemName)
Button(action: {
viewModel.addToList(ToDoModel(listItem: listItemName))
listItemName = ""
}) {
Image(systemName: "plus")
.font(.largeTitle)
.frame(width: 75, height: 75)
.foregroundColor(Color.white)
.background(Color.blue)
.clipShape(Circle())
}
}.frame(minWidth: 100, idealWidth: 150, maxWidth: 500, minHeight: 30, idealHeight: 40, maxHeight: 50, alignment: .leading)
.padding(.leading, 16)
.padding(.trailing, 16)
}.navigationBarTitle("To Do List", displayMode: .inline)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}

型号

struct ToDoModel: Identifiable, Codable {
var id = UUID()
var listItem: String = ""
}

ViewModel

class ToDoListViewModel: ObservableObject {
@Published var itemList = [ToDoModel]()
func addToList( _ item: ToDoModel) {
itemList.append(item)
}
}

您也可以尝试这种方法:

.onDelete { index in
// get the item from the reversed list
let theItem = viewModel.itemList.reversed()[index.first!]
// get the index of the item from the viewModel, and remove it
if let ndx = viewModel.itemList.firstIndex(of: theItem) {
viewModel.itemList.remove(at: ndx)
}
}

注意:这可能不是算法效率最高的方法。但是,对于List上的简单删除,它应该执行得很好。

.onDelete { offsets in
let reversed = Array(viewModel.itemList.reversed()) //get the reversed array -- use Array() so we don't get a ReversedCollection
let items = Set(offsets.map { reversed[$0].id }) //get the IDs to delete
viewModel.itemList.removeAll { items.contains($0.id) } //remove the items with IDs that match the Set
}

我发现反转索引集更直观。

index: 0, 1, 2, 3
index_reversed: 3, 2, 1, 0
3 - index_reversed = index

我通过创建一个新的集合并逐个插入项目来做到这一点(也许有更好的方法(。


ForEach(array.reversed()){
}
.onDelete { indexReversedSet in
var indexSet = IndexSet()
let maxIndex = array.count - 1
for indexReversed in indexReversedSet {
let index = maxIndex - indexReversed
indexSet.insert(index)
}
array.remove(atOffsets: indexSet)
}

最新更新