UICollectionView аварийно завершает работу при изменении порядка элементов на iOS10.x

Я попытался реализовать встроенное переупорядочение CollectionView, которое было представлено начиная с iOS10, в соответствии с этим руководством: http://nshint.io/blog/2015/07/16/uicollectionviews-now-have-easy-reordering/ и все работает нормально на iOS11, но вылетает на iOS10 при запуске перетаскивания любого элемента (ячейки) в UICollectionView

Вот мой код:

- (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;
        }
    }
}

и iOS 10 каждый раз вылетает в сети:

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

Отчет о сбое:

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

Я что-то забыл установить?

Буду очень признателен, если у кого-то есть идеи по этому поводу ...

Я думаю, что это должен быть [self.collectionView updateInteractiveMovementTargetPosition:[gesture locationInView:gesture.view]]; Обратите внимание, что это не self.view, а фактически gesture.view

staticVoidMan 12.04.2018 12:21

@staticVoidMan, извини, это у меня плохо. Когда я копировал и вставлял код, я по ошибке изменил guesture.view на self.view. Исходный код - [gesture locationInView: gesture.view], и он дает сбой только на iOS10.

RemembranceNN 12.04.2018 14:32

@staticVoidMan, кажется, я нашел место, где найти проблему. У меня есть собственный макет, унаследованный от UICollectionViewFlowLayout и переопределяющий в нем функцию targetIndexPathForInteractivelyMovingItem. Если прокомментировать это переопределение, переупорядочивание работы без сбоев. просто элемент перемещается на неправильный indexPath

RemembranceNN 12.04.2018 15:45

большой! вы также должны отметить свой ответ как принятый

staticVoidMan 12.04.2018 20:17
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
4
569
1

Ответы 1

Хорошо, кажется, я нашел причину этого сбоя и возможное решение. У меня есть собственный макет, унаследованный от UICollectionViewFlowLayout и переопределяющий в нем функцию targetIndexPathForInteractivelyMovingItem. Переместить предметы в правильное место. Я реализовал это так:

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

    return targetIndexPath;
}

И это отлично работает на iOS 11, но для iOS 10 indexPathForItemAtPoint по какой-то причине возвращает nil (я не уверен, почему) Поэтому мне пришлось добавить этот трюк, чтобы предотвратить сбой при переупорядочивании

- (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;
}

Другие вопросы по теме