Попытка начать переупорядочение в представлении сбора, когда переупорядочение уже выполняется - PullRequest
0 голосов
/ 25 сентября 2018

Я реализовал перетаскивание между двумя UICollectionViews.Иногда я получаю эту странную ошибку.

Assertion failure in -[UICollectionView _beginInteractiveMovementForItemAtIndexPath:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3698.54.4/UICollectionView.m:8459

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to begin reordering on collection view while reordering is already in progress'

Моя установка выглядит следующим образом:

  1. У меня есть два UICollectionViews (например, A & B)
  2. Переупорядочениевключен в обоих видах коллекции
  3. При перетаскивании элемента из A в B. Операция копируется
  4. При перетаскивании элемента из B в A. Операция удаляется из B. Aне выполняется.

Пока мой код выглядит следующим образом (абстрактная версия)

// Drop delegate

    func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
    print(#function)
    let destinationIndexPath: IndexPath
    if let indexPath = coordinator.destinationIndexPath {
        destinationIndexPath = indexPath
        self.performDrop(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)
    } else if collectionView.tag == CollectionView.timeline.rawValue {
        // Get last index path of collection view.
        let section = collectionView.numberOfSections - 1
        let row = collectionView.numberOfItems(inSection: section)
        destinationIndexPath = IndexPath(row: row, section: section)
        self.performDrop(coordinator: coordinator, destinationIndexPath: destinationIndexPath, collectionView: collectionView)
    }
}

func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -> UICollectionViewDropProposal {
    print(#function)
    if session.localDragSession != nil {
        // Trying to drag and drop an item within the app
        if collectionView.hasActiveDrag {
            // Trying to re-oder within the same collection view
            return UICollectionViewDropProposal(operation: .move, intent: .insertAtDestinationIndexPath)
        } else {
            // Trying to copy an item from another collection view
            return UICollectionViewDropProposal(operation: .copy, intent: .insertAtDestinationIndexPath)
        }
    } else {
        // Trying to drag and drop an item from a different app
        return UICollectionViewDropProposal(operation: .forbidden)
    }
}

// Drag delegate

    func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
    print(#function)
    var item: Item?
    if collectionView.tag == CollectionView.media.rawValue {
        item = mediaItems[indexPath.row]
    } else {
        item = StoryManager.sharedInstance.timelineItems[indexPath.row]
    }

    if let item = item {
        let itemProvider = NSItemProvider(object: item.id as NSString)
        let dragItem = UIDragItem(itemProvider: itemProvider)
        dragItem.localObject = item
        return [dragItem]
    }
    return []
}

Шаги для повторного создания

  1. Имеют два UICollectionViewsс реализованными выше методами делегата
  2. Оба должны охватывать весь экран
  3. Перетащите элемент из одного и попробуйте удерживать его поверх другого в направлении края экрана, делая вид, что его уроните
  4. Наблюдайте за тем, как предметы реорганизуются, освобождая место для нового предмета (чтобы вы уронили предмет)
  5. Отведите палец от экрана и посмотрите, как он выглядит, как если бы перетаскивание было отменено.
  6. Заметьте, что элементы, которые были переставлены,Oom для нового элемента остается прежним.Если у вас есть консольные журналы для методов делегата макета представления коллекции, вы можете заметить, что они продолжают вызываться
  7. Теперь, если вы попытаетесь перетащить элемент снова или попытаться отойти от экрана, приложение вылетает.

Если у кого-нибудь из вас есть какое-либо понимание происходящего, это очень помогло бы.

Ответы [ 2 ]

0 голосов
/ 16 апреля 2019

Похоже, что UICollectionViewDropDelegate метод dropSessionDidEnd вызывается каждый раз, когда кто-то попадает в эту "проблему".Я думаю, что это немного более элегантно, чтобы обеспечить "конец интерактивного движения" здесь:

func collectionView(_ collectionView: UICollectionView, dropSessionDidEnd session: UIDropSession) {
    timeline.endInteractiveMovement()
    media.endInteractiveMovement()
}
0 голосов
/ 25 сентября 2018

Прекращение любого интерактивного движения в месте размещения (UICollectionView) при запуске нового перетаскивания исправило мою проблему.Мне пришлось изменить мой метод UICollectionViewDragDelegate следующим образом:

    func collectionView(_ collectionView: UICollectionView, itemsForBeginning session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {

    var item: Item?
    if collectionView.tag == CollectionView.media.rawValue {
        item = mediaItems[indexPath.row]

// New line to fix the problem. 'timeline' is the IBOutlet of the UICollectionView I'm going to drop the item
        timeline.endInteractiveMovement()

    } else {
        item = StoryManager.sharedInstance.timelineItems[indexPath.row]

// New line to fix the problem. 'media' is the IBOutlet of the UICollectionView I'm going to drop the item
        media.endInteractiveMovement()

    }

    if let item = item {
        let itemProvider = NSItemProvider(object: item.id as NSString)
        let dragItem = UIDragItem(itemProvider: itemProvider)
        dragItem.localObject = item
        return [dragItem]
    }
    return []
}

Чтобы исправить сбой приложения при навигации, мне пришлось прекратить любое интерактивное движение в viewWillDisappear.

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

// 'media' and 'timeline' are the IBOutlets of the UICollectionViews I have implemented drag and drop
    timeline.endInteractiveMovement()
    media.endInteractiveMovement()
}

Надеюсь, Apple исправитэто в будущем выпуске.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...