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

Animate insertions and deletions. #69

Open
chriseidhof opened this issue Nov 6, 2013 · 5 comments
Open

Animate insertions and deletions. #69

chriseidhof opened this issue Nov 6, 2013 · 5 comments

Comments

@chriseidhof
Copy link

I think we should have support for animated insertions and deletions.

Probably a first step is to have support for the following methods (just like UICollectionView):

– insertItemsAtIndexPaths:
– moveItemAtIndexPath:toIndexPath:
– deleteItemsAtIndexPaths:

And

– performBatchUpdates:completion:

However, I haven't read through the internals of JNWCollectionView, so any ideas about how to implement this are very welcome.

@jwilling
Copy link
Owner

jwilling commented Nov 7, 2013

NB: This comment is going to be a bit disjointed as I'm still undecided on a large portion of this API.

So this is quite a difficult problem to solve well. If the cells weren't reusable it would really be a piece of cake, but alas they are reusable. The problem with implementing this is that keeping track of state becomes a nightmare.


UITableView utilizes the following API:

- beginUpdates
- endUpdates

- insertSections:withRowAnimation:
- deleteSections:withRowAnimation:
- reloadSections:withRowAnimation:
- moveSection:toSection:

- insertRowsAtIndexPaths:withRowAnimation:
- deleteRowsAtIndexPaths:withRowAnimation:
- reloadRowsAtIndexPaths:withRowAnimation:
- moveRowAtIndexPath:toIndexPath:

... and UICollectionView uses the following API:

- insertSections:
- deleteSections:
- reloadSections:
- moveSection:toSection:

- insertItemsAtIndexPaths:
- deleteItemsAtIndexPaths:
- reloadItemsAtIndexPaths:
- moveItemAtIndexPath:toIndexPath:

- performBatchUpdates:completion:

Both work reliably. However, there are two significant drawbacks to creating the API like this for JNWCollectionView.

  1. It forces the user to keep track of state. Now don't get me wrong, somebody has to keep track of state somewhere along the line or we won't know what to change. However, wouldn't it be nicer if we could keep track of state, inferring it from the current state of the model?
  2. We don't have NSFetchedResultsController on the Mac. A huge benefit of the changeset API that UITable/CollectionView use is that it can be tied in directly with NSFetchedResultsController. I do realize that it's somewhat easy to replicate these changesets using MOC change notifications (if using Core Data), however it seems like that's forcing users to change how they store their model data based on the API for displaying the aforementioned data. That seems a bit backwards.

What does this ideal API look like? Ideally it would be much more minimal than the current standards for granular updates. An initial approach would be to force the user to store their models in some sort of collection which we could then observe and perform diffs on when any sort of update occurs. However, this too is not a good approach since it forces the user to keep their data in memory, which would naturally be an issue for larger amounts of data.


Jumping abruptly from the public API, the internal implementation should most likely be based around the traditional changesets approach, no matter where we're getting the change notifications.

The challenge is keeping track of the following:

  • Which views should remain visible and added as a subview regardless of whether they're on-screen or not (e.g. animating while scrolling).
  • The position of items in an in-flight animation originating from an insertion or removal. This position might not be constant due to other insertions, removals, or moves happening around the cell itself.
  • Adjusting the scroll view bounds based on future insertions or removals.
  • Coalescing updates.

Jumping again to the animation side of things, I think UICollectionView take a good approach for handling insertions and removals. Namely:

- initialLayoutAttributesForAppearingItemAtIndexPath:
- finalLayoutAttributesForDisappearingItemAtIndexPath:

However, I think one issue that I have with the API is that it does not offer a way to customize the animations beyond adjusting the layout attributes. For example, let's way I wanted to insert a cell with a spring animation. With UICollectionView that'd be quite messy to accomplish. I'd need to insert the item without an animation and with the final layout attributes, then apply my own animation on the cell side, which just isn't the greatest.

To add a bit more flexibility we'd need to be able to let users define their own animations. One approach to this would be to use the current API UICollectionView uses for appearing / disappearing layout attributes, with one method added on. This method would be similar to -actionForLayer:forKey:, where the key path is the property which needs to be animated. If the user returns a valid CAAnimation subclass, it would be easy enough to set it on the animations dictionary before performing the animation itself.


Well that concludes the random jumble of thoughts I have about this. It really opens more questions than answers, but I want to think this through carefully before taking the more traditional approach to an API this important.

@chriseidhof
Copy link
Author

We have very rudimentary support for this in our branch (https://github.com/chriseidhof/JNWCollectionView/tree/item-spacing) it only works for one section. The code is still complex, we can simplify this a bit more. We did decide to use the UICollectionView API.

@jwilling
Copy link
Owner

@chriseidhof Looks very interesting! In case you all don't plan on continuing to work on that any more, I might pick up from where you left off once I have the motivation to get working on implementing this.

@chriseidhof
Copy link
Author

@jwilling currently, we're focused on shipping our product, and we probably won't have set apart time in the next months to clean it up and make it work for any use case. (e.g. section support, etc.).

@jwilling
Copy link
Owner

@chriseidhof No problem at all, I understand.

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

2 participants