4

I have a list with a ForEach that has the .ondelete function however it is very difficult to get the swipe action to work correctly (1 in 100 swipes work) and display the delete button. Once it does it all works correctly and the delete works.

struct ActivitySelectorView: View {

varibles here    

var body: some View {

    ZStack {
        //backgroundColor
        Color("\(activityToSave.category)Color")

        VStack {
            
            //Title Bar
            TitleBar(showingAlert: $showingAlert, showActivitySelector: $showActivitySelector, categoryName: categoryNames[(Int(String(activityToSave.category.last!)) ?? 1) - 1])
            
           
            List {
                SearchBar(text: $searchText)
                
                ForEach(fetchRequest.wrappedValue.filter({ searchText.isEmpty ? true : $0.name.contains(searchText) }), id: \.self) { activity in
                    
                    HStack {
                    
                        Text(activity.name.capitalized)
                            
                        Spacer()
                    }
                    .frame(height: 30)
                    .contentShape(Rectangle())
                    .onTapGesture {
                        self.showActivitySelector = false
                        self.activityToSave.activityName = activity.name.capitalized
                    }
                        
                }
                .onDelete(perform: deleteActivity)
            }
            
            .resignKeyboardOnDragGesture()
        }
        
        TextFieldAlert(isShowing: $showingAlert, text: $alertInput, category: activityToSave.category)
            .offset(x: 60, y: self.showingAlert ? -100 : screen.height)
    }
}

func deleteActivity(at offsets: IndexSet) {
    for index in offsets {
        let activity = fetchRequest.wrappedValue[index]
        viewContext.delete(activity)
    }
    do {
        try viewContext.save()
    } catch {
        print(error)
    }
}

Edit for more context

In ContentView I have a button which changes the offset of a view called AddActivityView seen here.

  //MARK: - Add activity view
        AddActivityView(
            showActivitySelector: $showActivitySelector,
            activityToSave: activityToSave,
            showAddActivity: $showAddActivity,
            isEditScreen: false,
            selectedDate: $daySelected,
            itemToDelete: $activityToDelete,
            showingNameEditor: $showCategoryNameEditor,
            category1Name: $category1Name,
            category2Name: $category2Name,
            category3Name: $category3Name,
            category4Name: $category4Name
        )
            .clipShape(RoundedRectangle(cornerRadius: 30, style: .continuous))
            .frame(width: screen.width, height: screen.height - 60, alignment: .leading)
            .offset(y: activityViewState.height)
            .offset(x: 0, y: showAddActivity ? 60 : screen.height)
            .animation(.easeInOut)
            .gesture(
                DragGesture()
                    .onChanged{ value in
                        if self.activityViewState.height > -1 {
                            self.activityViewState = value.translation
                        }
                    }
                    .onEnded{ value in
                        if self.activityViewState.height > 100 {
                            self.showAddActivity = false
                            self.showActivitySelector = false
                            self.showCategoryNameEditor = false
                            resetActivity(activityToSave)
                        }
                        self.activityViewState = .zero
                    }
            )

Then in that view there is a button which change offset of another view called ActivitySelectorView which is the view at the top which contains the list

 //MARK: - ActivitySelectorView
        ActivitySelectorView(filter: activityToSave.category, showActivitySelector: $showActivitySelector, activityToSave: activityToSave, allActivities: activities, categoryNames: categoryNames)
                .environmentObject(activityToSave)
                .frame(width: screen.width, height: screen.height)
                .offset(x: showActivitySelector ? 0 : screen.width)
                .offset(y: screen.minY)
                .offset(x: viewState.width)
                .animation(.easeInOut)
                
BlakePat
  • 75
  • 7
  • 1
    Please provide a minimum reproducible example if you want exact responses for your code (https://stackoverflow.com/help/minimal-reproducible-example). Looking quickly, I would guess that the TapGesture is taking priority over the onDelete swipe. Maybe look into simultaneousGestures or try moving the onTapGesture only onto the Text() object? – nicksarno Dec 10 '20 at 19:54
  • 1
    This has a lot of custom controls, so I can't reproduce it exactly. However, I was able to replace a bunch of them with generics and, for me, it's very easy to perform the delete gesture. Can you give more context? https://i.imgur.com/gUSi2uP.mp4 – Ky - Dec 10 '20 at 20:03
  • @nicksarno I tried commenting out the tap gesture and no luck. I will looking into simulatenousGestures. Thank you! – BlakePat Dec 10 '20 at 20:10
  • @BenLeggiero I added an edit for more context. Hopefully that helps. I have also tried commenting out DragGesture on AddActivityView and that did not help. Let me know if you need more info on something not included. – BlakePat Dec 10 '20 at 20:19
  • Take a look at this video https://www.youtube.com/watch?v=5PJL4xxEXJE&ab_channel=SeanAllen it might help you. – C0D3 Dec 02 '21 at 07:36

0 Answers0