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: {})
]
)
}
}
}
}
}
这是任务模型
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: {})
]
)
}
}
}
}
}