Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Swipe without removing the item from the list #69

Open
2 tasks done
james-ff opened this issue Mar 11, 2020 · 4 comments
Open
2 tasks done

[Feature] Swipe without removing the item from the list #69

james-ff opened this issue Mar 11, 2020 · 4 comments

Comments

@james-ff
Copy link

New Issue Checklist

Is your feature request related to a problem? Please describe.

If I do not remove the swiped item from the datasource an error occurs

[UICollectionView] Invalid update: invalid number of items in section 0.  The number of items contained in an existing section after the update (5) must be equal to the number of items contained in that section before the update (5), plus or minus the number of items inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out). - will perform reloadData. UICollectionView instance: <VerticalCardSwiper.VerticalCardSwiperView: 0x7fd828086000; baseClass = UICollectionView; frame = (0 0; 414 673); clipsToBounds = YES; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x600001be2c40>; layer = <CALayer: 0x600001590c20>; contentOffset: {-20, -40}; contentSize: {374, 2875}; adjustedContentInset: {40, 20, 90, 20}; layout: <VerticalCardSwiper.VerticalCardSwiperFlowLayout: 0x7fd82757c8d0>; dataSource: <VerticalCardSwiper.VerticalCardSwiper: 0x7fd82757c0c0; frame = (0 0; 414 673); autoresize = RM+BM; layer = <CALayer: 0x6000015904c0>>>; currentUpdate: [UICollectionViewUpdate - 0x7fd82bd21980: old:<UICollectionViewData: 0x600002d89180> new<UICollectionViewData: 0x600002d07800> items:<(
    "D(0,0)"
)>]

Describe the solution you'd like

I would like to configure the cardSwiper view to not remove an item when it is swiped (instead trigger an action), and later on when that action finishes I can remove the item programmatically.

Describe alternatives you've considered

I've considered re-adding the removed item immediately, but It feels like this would be a hack solution, which might cause strange animations

Additional context

none

@alobanov11
Copy link

alobanov11 commented Jul 5, 2020

Hi @james-ff, I had the same error. It was a stupid mistake:

private var films = [Film]() {
	didSet { self.cardSwiper.reloadData() }
}
...
func willSwipeCardAway(card: CardCell, index: Int, swipeDirection: SwipeDirection) {
	guard index < self.films.count else { return }
	self.films.remove(at: index)
}

I just removed didSet and it worked.

@JoniVR
Copy link
Owner

JoniVR commented Aug 6, 2020

Do you want the card to swipe away without having to update the datasource to reflect this? Or just block the card from swiping away?

To me personally it seems weird to want your datasource out of sync with the actual displayed data, I think this is why Apple does this too? I'm just forwarding the UICollectionView for the most part anyways.

@james-ff
Copy link
Author

james-ff commented Aug 6, 2020

Blocking the card from swiping away matches my intent here.

  • The idea being that swiping one direction could remove an item, and swiping the other would bring up a confirmation view.
  • The card would then slide back into position while a confirmation view appears and stay there if cancelled
  • In the case of confirmation the card could then be removed programmatically

Hope that clarifies it. In the meantime I add the item back in if the confirmation is cancelled.

@sevgjan
Copy link

sevgjan commented Aug 7, 2020

Hi @james-ff ,
I was able to achieve this by modifying internal func didSwipeAway method in VerticalCardSwiper.swift class, from:

 internal func didSwipeAway(cell: CardCell, swipeDirection direction: SwipeDirection) {
        if let indexPathToRemove = self.verticalCardSwiperView.indexPath(for: cell) {
            swipedCard = nil
            self.verticalCardSwiperView.performBatchUpdates({
                self.verticalCardSwiperView.deleteItems(at: [indexPathToRemove])
            }, completion: { [weak self] _ in
                self?.verticalCardSwiperView.collectionViewLayout.invalidateLayout()
                self?.verticalCardSwiperView.isUserInteractionEnabled = true
                self?.delegate?.didSwipeCardAway?(card: cell, index: indexPathToRemove.row, swipeDirection: direction)
            })
        }
    }

to:

internal func didSwipeAway(cell: CardCell, swipeDirection direction: SwipeDirection) {
        if let indexPathToRemove = self.verticalCardSwiperView.indexPath(for: cell) {
            swipedCard = nil
            self.verticalCardSwiperView.performBatchUpdates({
                if direction == .left {
                    self.verticalCardSwiperView.deleteItems(at: [indexPathToRemove])
                }
            }, completion: { [weak self] _ in
                self?.verticalCardSwiperView.collectionViewLayout.invalidateLayout()
                self?.verticalCardSwiperView.isUserInteractionEnabled = true
                self?.delegate?.didSwipeCardAway?(card: cell, index: indexPathToRemove.row, swipeDirection: direction)
            })
        }
    }

Hope this helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants