skip to Main Content

After removing all the items from a list and then adding the items back to the list, each list item is indented like it is in edit mode and swipe actions are unavailable. I only see the issue when I have the conditional checking if the array is empty.

struct TestView: View {
    @State var categories = ["dog", "cat"]

    var body: some View {
        VStack {
            if(categories.isEmpty){
                Button ("Add category"){
                    categories = ["dog", "cat"]
                }
            } else {
                List {
                    ForEach(categories.indices, id: .self) { i in
                        Text(categories[i])
                            .swipeActions(allowsFullSwipe: false) {
                                Button(role: .destructive) {
                                    categories.remove(at: i)
                                } label: {
                                    Label("Delete", systemImage: "trash.fill")
                                }
                            }
                    }
                }
            }
        }
    }
}

Before removing items from array:

before removing items

After removing items and adding new items to array:

after removing items

2

Answers


  1. here is an example that shows that deletion is not the problem

    struct TestView: View {
        @State var categories = ["dog", "cat"]
    
        var body: some View {
            VStack {
                if(categories.isEmpty){
                    Button ("Add category"){
                        categories = ["dog", "cat"]
                    }
                } else {
                    List {
                        ForEach(categories.indices, id: .self) { i in
                            Text(categories[i])
    //                            .swipeActions(allowsFullSwipe: false) {
    //                                Button(role: .destructive) {
    //                                    categories.remove(at: i)
    //                                } label: {
    //                                    Label("Delete", systemImage: "trash.fill")
    //                                }
    //                            }
                            .onTapGesture {
                                categories.remove(at: i)
                            }
                        }
                    }
                }
            }
        }}
    

    the problem is that after deleting an element from the list with swipeActions the list is supposed to reposition itself, doing so just after deleting the last element from the list with swipeActions you decide to disappear the list so it will not have the time to finish his action.

    I suggest the following code which works fine

    struct TestView: View {
        @State var categories = ["dog", "cat"]
    
    
        var body: some View {
            VStack {
                if(categories.isEmpty){
                    Button ("Add category"){
                        categories = ["dog", "cat"]
                    }
                }
                List {
                    ForEach(categories.indices, id: .self) { i in
                        Text(categories[i])
                        .swipeActions(allowsFullSwipe: false) {
                             Button(role: .destructive) {
                                 categories.remove(at: i)
                             } label: {
                                 Label("Delete", systemImage: "trash.fill")
                             }
                        }
                    }
                }
                 // don't display if categories.isEmpty
                .frame(height: categories.isEmpty ? 0 : nil)
            }
        }}
    

    enter image description here

    Login or Signup to reply.
  2. Here’s a possible solution. You could try using onDelete for this, documentation is here. I also included onMove if needed and added a button which is only active when the array is empty.

    struct ContentView: View {
        @State private var animals = [
            "Dog",
            "Cat",
        ]
        
        var body: some View {
            NavigationView {
                List {
                    ForEach(animals, id: .self) { animal in
                        Text(animal)
                    }
                    .onDelete { self.delete(at :$0) }
                    .onMove { self.move(from: $0, to: $1) }
                }
                .navigationTitle("Animals")
                .toolbar {
                    ToolbarItem(placement: .navigationBarLeading) {
                        Button(action: {
                            self.animals = [
                                "Dog",
                                "Cat",
                            ]
                        }, label: {
                            Label("Add", systemImage: "plus")
                                .labelStyle(.iconOnly)
                        }).disabled(!animals.isEmpty)
                    }
                    ToolbarItem(placement: .navigationBarTrailing) {
                        EditButton()
                    }
                }
            }
        }
        
        func delete(at: IndexSet) {
            for i in at {
                animals.remove(at: i)
            }
        }
        
        func move(from: IndexSet, to: Int) {
            animals.move(fromOffsets: from, toOffset: to)
        }
    }
    

    enter image description here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search