UICollectionView moveItemAtIndexPath:toIndexPath: issues moving items not on screen

12,321

It looks like UICollectionView is reusing cells in such a way as to make your animation look bad. Any cells that go offscreen become available for reuse.

So why is your animation looking funky?

The starting and ending location of a cell, and if it gets hidden or not, is all taken care of automatically when you move cells around. For those animations to look good, you need to also update your data source, as it appears the code uses that to determine where cells should start and end during the animation.

Before you call your index update block, make sure your data source is updated with the new index locations. That way Apple's code has the information it needs to move your cells around in a more, lets say, aesthetically pleasing manner.

From the Apple documentation on UICollectionViews:

To insert, delete, or move a single section or item, you must follow these steps:

  1. Update the data in your data source object.
  2. Call the appropriate method of the collection view to insert or delete the section or item.

It is critical that you update your data source before notifying the collection view of any changes. The collection view methods assume that your data source contains the currently correct data. If it does not, the collection view might receive the wrong set of items from your data source or ask for items that are not there and crash your app.

Share:
12,321
marmor
Author by

marmor

Updated on July 26, 2022

Comments

  • marmor
    marmor almost 2 years

    I'm trying to animate a re-sort of items in UICollectionView on iOS 6.

    I wrote this code:

        NSMutableDictionary *from = [NSMutableDictionary dictionaryWithCapacity:self.count];
        for (int ii = 0; ii < self.count; ii++) {
            MyItem item = [self getItemAtIndex:(NSInteger)ii];
            [from setObject:[NSNumber numberWithInt:ii] forKey:[NSNumber numberWithInt:item.id]];
        }
    
        [self sort];
    
        [self.collectionView performBatchUpdates:^{
            for (int ii = 0; ii < self.count; ii++) {
                MyItem item = [self getItemAtIndex:(NSInteger)ii];
                NSNumber *prevPos = (NSNumber *)[from objectForKey:[NSNumber numberWithInt:item.id]];
                if ([prevPos intValue] != ii) {
                    NSIndexPath *from = [NSIndexPath indexPathForItem:prevPos.intValue inSection:0];
                    NSIndexPath *to = [NSIndexPath indexPathForItem:ii inSection:0];
                    [self.collectionView moveItemAtIndexPath:from toIndexPath:to];
                }
            }
        } completion:nil];
    

    So first, I'm saving all the current locations of the items in a dictionary, then I'm sorting the items into new positions, then I'm going over all items, and moving them from the old position to the new one.

    This works great when all items are displayed on the screen, but if the the list if longer then 10 which makes some items not currently visible (since they are above or below the visible section of the list), it causes these items to suddenly pop into existence in visible indexes and get animated into other places, and when the animation stops they are hidden. This looks really bizarre as there are items that appear on top of others...

    Is this an issue with iOS 6 UICollectionView, and am I doing something wrong here?

  • marmor
    marmor over 11 years
    Hey @redlightbulb, thanks for the reply, the call [self sort]; updates the data source to the new positions. So, I think you're right that the reusable cells gets in the way of the animation, but I can't think of a good solution for this. Can you suggest a fixed code?
  • redlightbulb
    redlightbulb over 11 years
    Hi @marmor - What layout are you using? A method that controls where a cell begins when you are inserting it is initialLayoutAttributesForInsertedItemAtIndexPath. If you put logic in there to place your cells either above or below the current visible area it should allow you to see your cells "Flying in" from off screen. Let me know if that helps! (Link: developer.apple.com/library/ios/#documentation/uikit/referen‌​ce/…)
  • marmor
    marmor over 11 years
    I'm using UICollectionView in Grid layout, that's a good tip, I'll check it out...