SwiftUI:如何删除 VStack 中的 ForEach 行?

SwiftUI : How I can delete row of ForEach in VStack?

这是任务模型

import Foundation
import SwiftUI


struct TaskModel: Identifiable, Codable {
    var id = UUID().uuidString
    var title : String
    var selectedColor : Color
    var remindedTime : Int
    var taskDate : Date
}

这是我试过的 ViewModel

    import Foundation
    import SwiftUI
    
    class CalendarViewModel : ObservableObject {
        
        @Published var tasks : [TaskModel] = []
        @Published var currentMonth : Int = 0
        
    
        func addTask(title : String, selectedColor : Color, reminderTime : Int, taskDate : Date) {
            let newTask = TaskModel(title: title, selectedColor: selectedColor, remindedTime: reminderTime * 60, taskDate: taskDate)
            tasks.append(newTask)
        }
        
        func deleteTask(task : TaskModel) {
            if let index = tasks.firstIndex(where: {[=11=].id == task.id }) {
                tasks.remove(at: index)
            }
        }

这是我尝试删除行的 ForEach

VStack {
                    ForEach(vm.tasks.filter({vm.isSameDay(date1: [=12=].taskDate, date2: currentDate)})) { task in
                        TaskRowView(task: task)
                            .actionSheet(isPresented: $isShowActionSheet) {
                                ActionSheet(title: Text("Settings"), message: Text("Press the button that what you want to do "), buttons: [
                                    .cancel(), .destructive(Text("Delete"), action: {
                                        vm.deleteTask(task: task)
                                    }), .default(Text("Edit"), action: {
                                        
                                    })
                                ])
                            }
                    }
                    
                    .onLongPressGesture {
                        isShowActionSheet.toggle()
                    }
                 }

这是我的应用程序视图的图片。

奇怪的是当我试图删除列表的第二行时,第一行被删除,第二行被留下。

但是,我找不到我的遗漏点。

最简单的实现方式是使用可选的选择变量和 .actionSheet() 的自定义绑定。请看下面的代码。我评论了重要的部分。出于演示目的,我还将您的代码更改为 Minimal Reproducible Example (MRE)

struct ContentView: View {
    
    @State var tasks = Array(1...20).map( { TaskModel(title: "Task \([=10=])") })
    // This is your optional selection variable
    @State var selectedRow: TaskModel?
    
    var body: some View {
        VStack {
            ForEach(tasks) { task in
                Text(task.title)
                    // put the .onLongPressGesture() on the row itself
                    .onLongPressGesture {
                        // set selectedRow to the task
                        selectedRow = task
                    }
                    // This creates a custom binding
                    .actionSheet(isPresented: Binding<Bool>(
                        // the get returns the Bool that is the comparison of selectedRow and task
                        // if they are equal, the .actionSheet() fires
                        get: { selectedRow == task },
                        // when done, .actionSheet() sets the Binding<Bool> to false, but we intercept that
                        // and use it to set the selectedRow back to nil
                        set: { if ![=10=] {
                            selectedRow = nil
                        }})) {
                        ActionSheet(
                            title: Text("Settings"),
                            // added task.title to prove the correct row is in the ActionSheet
                            message: Text("Press the button for \(task.title)"),
                            buttons: [
                                .cancel(),
                                .destructive(Text("Delete"), action: {}),
                                .default(Text("Edit"), action: {})
                            ]
                        )
                    }
            }
        }
    }
}