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

Using An Infinite Number of Cards #13

Closed
CJxD opened this issue Aug 29, 2019 · 6 comments
Closed

Using An Infinite Number of Cards #13

CJxD opened this issue Aug 29, 2019 · 6 comments
Labels
enhancement New feature or request

Comments

@CJxD
Copy link

CJxD commented Aug 29, 2019

Is there a way to make an unlimited swipe stack, as Tinder does? Can the number of cards be updated dynamically?


I've tried returning Int.max in numberOfCards, and for testing, I do a modulus on the cardForIndexAt parameter as such: return MyCard(image: cardImages[index % numImages])

This doesn't work out as it seems to load all images in the stack, so the application just crashes when trying to load a practically infinite number of UIViews.

@mac-gallagher
Copy link
Owner

mac-gallagher commented Aug 30, 2019

Hey @CJxD, this is a great question and one I have thought about quite a lot.

TL;DR - Not yet

The SwipeCardStack class is modeled after UITableView which only displays a finite amount of cells at a time. If you consider the cards as cells, this question can be rephrased as

Can you have an infinitely scrolling UITableView?

The answer is, of course, yes, but how?

The solution is Pagination. One way to paginate is to fetch your next cell's data model on a background thread whenever you run out of cells while scrolling. To update your tableview, you append the fetched data to your data model list and call reloadData on the main thread.

Note: this is not the best solution. Ideally you would pre-fetch your data (check out UITableViewDataSourcePrefetching!), but let's run with this for now.

So you might have something like this:

func cellForRow(at indexPath: IndexPath) -> UITableViewCell?
   if indexPath.row >= models.currentCount - 1 { // asking for the last cell, so we need more data soon!
      fetchMoreModels()
   }
    return YourCell(data: models[indexPath.row])
  }

Unfortunately, this approach doesn't work for SwipeCardStack. Any call to reloadData removes the swipe history, so calling reloadData would just displays the card stack as before, just with the new cards queued up.

This is a very difficult problem and one I hope we can solve eventually! It's particularly difficult when you factor in the card stack shift and undo functions.


By the way, the reason it crashes is because the SwipeCardStack tries to capture the state of your swipe history after every swipe (and upon first load). It tries to create an array of size Int.max. The card stack is actually only loads those images which it is currently displaying.

Give it a try with 10,000 cards - it should be fine (although potentially slow).

@mac-gallagher mac-gallagher pinned this issue Aug 30, 2019
@mac-gallagher mac-gallagher changed the title Using a neverending list of swipe cards Using An Infinite Number of Cards Aug 30, 2019
@mac-gallagher mac-gallagher added the enhancement New feature or request label Sep 2, 2019
@CJxD
Copy link
Author

CJxD commented Sep 2, 2019 via email

@nservidio nservidio mentioned this issue Nov 19, 2019
@dfmarulanda
Copy link

How did you solve the undo function when you're at the first item of the new stack of data @CJxD ?

@CJxD
Copy link
Author

CJxD commented Mar 5, 2020

Hi @dfmarulanda, sorry for the slow reply.

For me I haven't actually needed this ability (I use undo to return a card back to its original position after swiping up to share), however, I would recommend using a ring buffer that's larger than your stack size by the number of times you allow undos, and reload the data when undo is called.

The data source for the stack will be all cards in between the head and tail of the buffer.

If undo is asking for a card that is not in the current stack, then the head of the buffer is moved back one and the data is reloaded.

For example, if you allow 2 undos, and your stack is of size 5, then your ring buffer is size 7:

First load:
([1], [2], [3], [4], [5], [ ], [ ])
  ^head               ^tail

Second load:
([8], [9], [10], [4], [5], [6], [7])
            ^tail           ^head

Undo 1:
([8], [9], [10], [4], [5], [6], [7])
            ^tail      ^head

Undo 2:
([8], [9], [10], [4], [5], [6], [7])
            ^tail ^head

Undo 3: not allowed, does nothing.

@mac-gallagher
Copy link
Owner

Hey @CJxD and others. Happy to announce that infinite card stacks are now supported as of version 3.0.1. Take a look at the documentation on Adding News Cards

Cheers,
Mac

@mac-gallagher mac-gallagher unpinned this issue Jul 10, 2020
@CJxD
Copy link
Author

CJxD commented Jul 10, 2020

Awesome!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants