0

I tried to implement built-in CollectionView reordering that was presented starting from iOS10 according to this guide: http://nshint.io/blog/2015/07/16/uicollectionviews-now-have-easy-reordering/ and everything work fine on iOS11, but have crash on iOS10 when starting drag any item (cell) in UICollectionView

Here is my code:

- (void)addCollectionViewGestureRecognizers
{
    if (!self.panGesture)
    {
        // gesture to drag and reorder tiles
        self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleCollectionViewPanGesture:)];
            [self.collectionView addGestureRecognizer:self.panGesture];
    }
}

- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath
{
    return YES;
}

- (void)collectionView:(UICollectionView *)collectionView moveItemAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
    CLog(@"Item moved from index path: %@ to index path: %@", sourceIndexPath, destinationIndexPath);
}

- (void)handleCollectionViewPanGesture:(UIPanGestureRecognizer *)gesture
{
    switch(gesture.state)
    {
        case UIGestureRecognizerStateBegan:
        {
            NSIndexPath *selectedIndexPath = [self.collectionView indexPathForItemAtPoint:[gesture locationInView:self.collectionView]];
            if(selectedIndexPath)
            {
                [self.collectionView beginInteractiveMovementForItemAtIndexPath:selectedIndexPath];
            }
            break;
        }
        case UIGestureRecognizerStateChanged:
        {
            [self.collectionView updateInteractiveMovementTargetPosition:[gesture locationInView:gesture.view]];
            break;
        }
        case UIGestureRecognizerStateEnded:
        {
            [self.collectionView endInteractiveMovement];
            break;
        }
        default:
        {
            [self.collectionView cancelInteractiveMovement];
            break;
        }
    }
}

and iOS 10 every time crashes on line:

[self.collectionView updateInteractiveMovementTargetPosition:[gesture locationInView:guesture.view]];

Crash report:

0   CoreFoundation                      0x0000000118f8bb0b __exceptionPreprocess + 171
1   libobjc.A.dylib                     0x0000000118961141 objc_exception_throw + 48
2   CoreFoundation                      0x0000000118ec0443 -[__NSArrayM insertObject:atIndex:] + 1603
3   UIKit                               0x00000001166f3577 -[UICollectionView _getOriginalReorderingIndexPaths:targetIndexPaths:] + 501
4   UIKit                               0x00000001166e2e50 -[UICollectionView _viewAnimationsForCurrentUpdate] + 7338
5   UIKit                               0x00000001166e7bf3 __71-[UICollectionView _updateWithItems:tentativelyForReordering:animator:]_block_invoke.2012 + 197
6   UIKit                               0x0000000115e4c08e +[UIView(Animation) performWithoutAnimation:] + 90
7   UIKit                               0x00000001166e682d -[UICollectionView _updateWithItems:tentativelyForReordering:animator:] + 3856
8   UIKit                               0x00000001166e0b33 -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:] + 17030
9   UIKit                               0x00000001166e91cd -[UICollectionView _endUpdatesWithInvalidationContext:tentativelyForReordering:animator:] + 71
10  UIKit                               0x00000001166e9514 -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:animator:] + 437
11  UIKit                               0x00000001166e933c -[UICollectionView _performBatchUpdates:completion:invalidationContext:tentativelyForReordering:] + 91
12  UIKit                               0x00000001166f09a3 -[UICollectionView _updateReorderingTargetPosition:forced:] + 1467
13  UIKit                               0x00000001166f122a -[UICollectionView updateInteractiveMovementTargetPosition:] + 29
14  myAPP                                 0x000000010dcb3b26 -[MenuCollectionViewController handleCollectionViewPanGesture:] + 710
15  UIKit                               0x00000001162c8f59 -[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 57
16  UIKit                               0x00000001162d0d57 _UIGestureRecognizerSendTargetActions + 109
17  UIKit                               0x00000001162ce70b _UIGestureRecognizerSendActions + 225

Am I forgot to set something?

I will very appreciate if someone have any ideas regarding this...

RemembranceNN
  • 280
  • 3
  • 8
  • i think it should be `[self.collectionView updateInteractiveMovementTargetPosition:[gesture locationInView:gesture.view]];` Note that it is not `self.view` but infact `gesture.view` – staticVoidMan Apr 12 '18 at 10:21
  • @staticVoidMan, sorry, that's my bad. When I was copy & pasting code I changed guesture.view to self.view by mistake. Original code is [gesture locationInView:gesture.view] and it has crash on iOS10 only – RemembranceNN Apr 12 '18 at 12:32
  • @staticVoidMan, seem I found a place where to find a problem. I have custom layout inherited from UICollectionViewFlowLayout and override targetIndexPathForInteractivelyMovingItem function in it. If comment this override, reordering work with no crash. just item moving to incorrect indexPath – RemembranceNN Apr 12 '18 at 13:45
  • great! you should mark your answer as accepted too – staticVoidMan Apr 12 '18 at 18:17

1 Answers1

0

Ok, seems I found a reason of that crash and possible solution. I have custom layout inherited from UICollectionViewFlowLayout and override function targetIndexPathForInteractivelyMovingItem in it. To move items to correct place. I implemented it like this:

- (NSIndexPath*)targetIndexPathForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath withPosition:(CGPoint)position
{
    NSIndexPath *targetIndexPath = [self.collectionView indexPathForItemAtPoint:position];

    return targetIndexPath;
}

And this works fine on iOS 11, but for iOS 10 indexPathForItemAtPoint returns nil for some reason (I don't sure why) So I had to add this trick to prevent crash on reordering

- (NSIndexPath*)targetIndexPathForInteractivelyMovingItem:(NSIndexPath *)previousIndexPath withPosition:(CGPoint)position
{
    NSIndexPath *targetIndexPath = [self.collectionView indexPathForItemAtPoint:position];

    if (!targetIndexPath) // on iOS10 indexpath can be nil by some reason
    {
        targetIndexPath = [NSIndexPath indexPathForRow:0 inSection:0];
    }

    return targetIndexPath;
}
RemembranceNN
  • 280
  • 3
  • 8