Delete specific element from array in ForEach

I have a tasks app, where I want to remove the task when the user taps the done button. I want to remove the task the user tapped 'done' but idk how, can someone help mii?

Note that I have an outdated Mac running macOS 12 & Xcode 13 so not everything up to date is possible.

Simplified version of the code follows:

import SwiftUI

struct Task: Identifiable {
    let id = UUID()
    var name: String
}

struct ContentView: View {
    @State var tasks = [
    Task(name: "task 1"),
    Task(name: "task 2"),
    Task(name: "task 3")
    ]
    var body: some View {
        List {
            ForEach(tasks) { task in
                HStack {
                    Text(task.name)
                    Spacer()
                    Button("Done!") {
                        tasks.remove(at: 0) //idk how to remove :(
                    }
                }
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Answered by Claude31 in 761871022

Welcome to the forum.

You remove at : 0, so you remove always the first element.

Change with this:

                    Button("Done!") {
                        tasks.removeAll(where: {$0.name == task.name }) // (at: 0) //idk how to remove :(
                    }

If OK, don't forget to close the thread by marking this answer as correct. Otherwise explain what problem you have. Good continuation.

Accepted Answer

Welcome to the forum.

You remove at : 0, so you remove always the first element.

Change with this:

                    Button("Done!") {
                        tasks.removeAll(where: {$0.name == task.name }) // (at: 0) //idk how to remove :(
                    }

If OK, don't forget to close the thread by marking this answer as correct. Otherwise explain what problem you have. Good continuation.

Hi @yoyboi ,

@Claude31 's comment is correct, but you should use id instead of name. By making Task conform to Identifiable, you have promised each item has a unique ID. You want to delete based on these id's since names can be the same. If you name two elements the same thing, both will be removed.

eg: tasks.removeAll(where: {$0.id == task.id })

@yoyboi ,

As you are learning, here is another option, using remove, by replacing the Done! button by onDelete (but in this case, an explicit button may be a better UI design, unless you need the real estate in the cell).

struct ContentView: View {
    @State var tasks = [
    Task(name: "task 1"),
    Task(name: "task 2"),
    Task(name: "task 3")
    ]

    var body: some View {
        List {
            ForEach(tasks) { task in
                    Text(task.name)
                }
            .onDelete(perform: { indexSet in  tasks.remove(atOffsets: indexSet) } )
        }
    }
}
Delete specific element from array in ForEach
 
 
Q