JTron
JTron

Reputation: 13

SwiftUI ForEach.onDelete doesn't work correctly in TabView

I have tried to implement a basic list with a ForEach loop. I've tried with Both a hashable struct and basic array Using ForEach(..., id: \.self) as shown below. Whenever it's inside a tab view and changing to EditMode.active, you have to press the - for about a sec as if it's a LongPressGesture() until it will show the swipe to delete.

Example of problem

struct HashArray: Hashable {
    let id = UUID()
    init(number: Int) {
        self.number = number
    }
    let number: Int
}

struct TabStuff: View {
    @State var markers: [Int] = [1, 2, 3, 4, 5]
    @State var testArray: [HashArray] = [HashArray(number: 0), HashArray(number: 1), HashArray(number: 2), HashArray(number: 3)]
    var body: some View {
        VStack {
            EditButton()
            List {
                ForEach(testArray, id: \.id) { marker in
                    Text("Number: \(marker.number)")
                }.onDelete(perform: { indexSet in
                    markers.remove(atOffsets: indexSet)
                })
            }
        }
    }
}

struct OtherView: View {
    @State var markers: [Int] = [1, 2, 3, 4, 5]
    var body: some View {
        VStack {
            EditButton()
            List {
                ForEach(markers, id: \.self) { marker in
                   Text("\(marker)")
                }.onDelete(perform: { indexSet in
                    markers.remove(atOffsets: indexSet)
                })
            }
        }
    }
}

both of which don't work when putting inside of a tab view like so

struct ContentView: View {
    @State var selectedTab: NavigationTab = .list

    var body: some View {
        TabView(selection: $selectedTab) {
            TabStuff()
                .onTapGesture {
                    selectedTab = .list
                }
                .tabItem {
                    Text("List Test")
                }

            OtherView()
                .onTapGesture {
                    selectedTab = .secondView
                }.tabItem {
                    Text("Second View")
                }

        }
    }
}

Any ideas on how to get it to react appropriately?

Upvotes: 1

Views: 874

Answers (1)

nicksarno
nicksarno

Reputation: 4245

It's because you have an .onTapGesture() on the entire view that is taking priority when a user taps anywhere in your view.

The tab items will automatically let you switch between tabs without having to update the selection, so you can just remove the tap gesture entirely. However, if you need to update the selectedTab when switching, you can use a .tag() modifier on the .tabItem.

        TabStuff()
            // REMOVE THIS
            //.onTapGesture {
            //    selectedTab = .list
            //}
            .tabItem {
                Text("List Test")
                    .tag(NavigationTab.list) // ADD THIS
            }

Upvotes: 3

Related Questions