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

Posted

技术标签:

【中文标题】如何使用 .reversed() 处理 SwiftUI 列表数组的 .onDelete【英文标题】:How to handle .onDelete for SwiftUI list array with .reversed() 【发布时间】:2021-12-31 16:18:46 【问题描述】:

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

请参阅下面的代码。谢谢!

内容视图

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 = ""

视图模型

class ToDoListViewModel: ObservableObject 
    @Published var itemList = [ToDoModel]()

    func addToList( _ item: ToDoModel) 
        itemList.append(item)
    

【问题讨论】:

【参考方案1】:

警告:这可能不是算法效率最高的方法。但是,对于 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

【讨论】:

【参考方案2】:

你也可以试试这个方法:

.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)
    

【讨论】:

以上是关于如何使用 .reversed() 处理 SwiftUI 列表数组的 .onDelete的主要内容,如果未能解决你的问题,请参考以下文章

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

Swift 3:加入reversed()数组时出错

Swift for循环语句,注意跟以前的不一样

Python 中的反转字符串:reversed()切片等

java8的thenComparing如何reversed()倒序

Python 中的反转字符串:reversed()切片等