我如何使用位于列表内部的按钮删除列表中的项目?

huangapple go评论147阅读模式
英文:

How would I delete items from a list with a button inside that list?

问题

SwiftUI
[这是列表和按钮的代码]

  1. ForEach(items, id: \.self) { current in
  2. VStack(alignment: .leading) {
  3. Text("\(current.task)")
  4. .padding(2)
  5. Text("\(dateFormatter.string(from: current.date))")
  6. Button(action: {},
  7. label: {
  8. Image(systemName:
  9. "checkmark.rectangle.fill")
  10. .resizable()
  11. .frame(width: 50, height: 35)
  12. })
  13. }
  14. }

Items 是包含字符串和日期的数组。以下是其代码:

  1. @State var items: [Tasks] = [Tasks(task: "测试", date: Date())]

这是 Tasks 结构体:

  1. struct Tasks: Hashable {
  2. let task: String
  3. let date: Date
  4. }

这是我的列表视图

我希望用户能够点击每个列表项下面的按钮,以删除该列表项。我目前使用 onDelete 方法,但我更希望在每个列表项下面有一个确认按钮,允许用户删除该列表项。

  1. @State var counter = -1

我尝试使用一个计数器,使其在 ForEach 循环运行时递增,并在该 ForEach 循环内创建一个等于计数器值的新变量。然而,我无法在按钮内访问该变量以用作索引。

英文:

SwiftUI
[This is the code for the list and my button]

  1. ForEach(items, id: \.self) { current in
  2. VStack(alignment: .leading) {
  3. Text("\(current.task)")
  4. .padding(2)
  5. Text("\(dateFormatter.string(from: current.date))")
  6. Button(action: {},
  7. label: {
  8. Image(systemName:
  9. "checkmark.rectangle.fill")
  10. .resizable()
  11. .frame(width: 50, height: 35)
  12. })
  13. }

Items is my array containing a string and a date. Here is the code for it:

  1. @State var items:[Tasks] = [Tasks(task: "Test", date: Date())]

And here is Tasks:

  1. struct Tasks: Hashable {
  2. let task: String
  3. let date: Date
  4. }

This is my list view

I want to have a user be able to click a button under each list item and it will remove that list item. I am currently using the onDelete method but I would prefer to have a confirm button in each list item that would allow the user to remove that list item.

  1. @State var counter = -1

I tried using a counter that would increase by 1 each time the ForEach loop ran and create a new variable inside of that ForEach loop equal to it. However I could not access the variable inside of the button to use as an index.

答案1

得分: 1

根据您当前的代码结构,假设每个 task: String 都是唯一的,您可以将以下代码添加到您的 Button 操作中:

  1. Button(action: {
  2. if let index = items.firstIndex(where: {$0.task == current.task}) {
  3. items.remove(at: index)
  4. }
  5. },
  6. label: {
  7. Image(systemName: "checkmark.rectangle.fill")
  8. .resizable()
  9. .frame(width: 50, height: 35)
  10. })

然而,为了使代码更加健壮,建议为您的 Task 添加一个 id 属性,并同时重命名它,因为Swift已经将 Task 定义为其异步/等待框架的一部分。

以下是我用于测试我的答案的完整代码:

  1. struct MyTask: Identifiable, Hashable {
  2. let id = UUID()
  3. let task: String
  4. let date: Date
  5. }
  6. struct ContentView: View {
  7. @State var items:[MyTask] = [
  8. MyTask(task: "Test1", date: Date()),
  9. MyTask(task: "Test2", date: Date().addingTimeInterval(60*60*24*44)),
  10. MyTask(task: "Test3", date: Date().addingTimeInterval(60*60*24*88))
  11. ]
  12. var body: some View {
  13. ForEach(items) { current in
  14. VStack(alignment: .leading) {
  15. Text(current.task).padding(2)
  16. Text(dateFormatter.string(from: current.date))
  17. Button(action: {
  18. if let index = items.firstIndex(where: {$0.id == current.id}) {
  19. items.remove(at: index)
  20. }
  21. },
  22. label: {
  23. Image(systemName: "checkmark.rectangle.fill").resizable()
  24. .frame(width: 50, height: 35)
  25. })
  26. }
  27. }
  28. }
  29. var dateFormatter: DateFormatter = {
  30. let frmt = DateFormatter()
  31. frmt.dateFormat = "yyyy-MMM-dd"
  32. return frmt
  33. }()
  34. }

请注意,我已经将 HTML 实体(例如 <")转换为正常的Swift代码。

英文:

Using your current code structure, assuming each task: String is unique, you could just add this to your Button action:

  1. Button(action: {
  2. if let index = items.firstIndex(where: {$0.task == current.task}) {
  3. items.remove(at: index)
  4. }
  5. },
  6. label: {
  7. Image(systemName: "checkmark.rectangle.fill")
  8. .resizable()
  9. .frame(width: 50, height: 35)
  10. })

However, it would be more robust to add an id property to your Task, and
at the same time rename it, because Swift already defines Task as part of its async/await framework.

Here is the complete code I use to test my answer:

  1. struct MyTask: Identifiable, Hashable { // <--- here
  2. let id = UUID() // <--- here
  3. let task: String
  4. let date: Date
  5. }
  6. struct ContentView: View {
  7. @State var items:[MyTask] = [
  8. MyTask(task: "Test1", date: Date()),
  9. MyTask(task: "Test2", date: Date().addingTimeInterval(60*60*24*44)),
  10. MyTask(task: "Test3", date: Date().addingTimeInterval(60*60*24*88))
  11. ]
  12. var body: some View {
  13. ForEach(items) { current in // <--- here
  14. VStack(alignment: .leading) {
  15. Text(current.task).padding(2) // <--- here
  16. Text(dateFormatter.string(from: current.date)) // <--- here
  17. Button(action: {
  18. // --- here
  19. if let index = items.firstIndex(where: {$0.id == current.id}) {
  20. items.remove(at: index)
  21. }
  22. },
  23. label: {
  24. Image(systemName: "checkmark.rectangle.fill").resizable()
  25. .frame(width: 50, height: 35)
  26. })
  27. }
  28. }
  29. }
  30. var dateFormatter: DateFormatter = {
  31. let frmt = DateFormatter()
  32. frmt.dateFormat = "yyyy-MMM-dd"
  33. return frmt
  34. }()
  35. }

huangapple
  • 本文由 发表于 2023年2月19日 06:31:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75496794.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定