title: Swift. Correctly reordering multiple items at once in a collectionView using drag and drop
body: <p>Ive now been stuck for over 2 weeks on how to drag and drop multiple items at once <em>within</em> a collectionView (ie <em>reordering</em> multiple items within a collectionView) using the new ios11 drag &amp; drop protocols. I can't get the cells to consistently reorder correctly. </p>
  
  <p>Ive tried using placeholders but that appears to be more targeted for remote drags into a collectionView with async data loads.</p>
  
  <p>Ive tried following instructions given in an answer within a blog post </p>
  
  <p><a href="https://hackernoon.com/drag-it-drop-it-in-collection-table-ios-11-6bd28795b313" rel="nofollow noreferrer">https://hackernoon.com/drag-it-drop-it-in-collection-table-ios-11-6bd28795b313</a></p>
  
  <p>where the instructions given (as an answer in the list of questions at the end of the post) was as follows </p>
  
  <p>Reordering multiple items in the same collection view is a bit tedious and need to be handled manually.</p>
  
  <p>First of all, use UICollectionViewDropIntent as .unspecified for .move UIDropOperation in the UICollectionViewDropProposal while returning from collectionView(_:dropSessionDidUpdate:withDestinationIndexPath:), i.e.</p>
  
  <pre><code>func collectionView(_ collectionView: UICollectionView, dropSessionDidUpdate session: UIDropSession, withDestinationIndexPath destinationIndexPath: IndexPath?) -&gt; UICollectionViewDropProposal
  {
      return UICollectionViewDropProposal(operation: .move, intent:  .unspecified)
  }
  </code></pre>
  
  <p>Secondly, you need to handle the insertion and deletion of each item that you want to reorder in the collection view explicitly. Example:</p>
  
  <pre><code>let items = coordinator.items
  var dIndexPath = destinationIndexPath
  if dIndexPath.row &gt;= collectionView.numberOfItems(inSection: 0)
  {
    dIndexPath.row = collectionView.numberOfItems(inSection: 0) - 1
  }
  var sourceIndexPaths = [IndexPath]()
  var destinationIndexPaths = [IndexPath]()
  for item in items
  {
    if let sourceIndexPath = item.sourceIndexPath
    {
      sourceIndexPaths.append(sourceIndexPath)
      destinationIndexPaths.append(dIndexPath)
      self.items2.remove(at: sourceIndexPath.row)
      self.items2.insert(item.dragItem.localObject as! String, at: dIndexPath.row)
      dIndexPath = IndexPath(row: dIndexPath.row + 1, section: 0)
    }
  }
  collectionView.performBatchUpdates({
    if collectionView === self.collectionView2
    {
      collectionView.deleteItems(at: sourceIndexPaths)
      collectionView.insertItems(at: destinationIndexPaths)
    }
  })
  </code></pre>
  
  <p>This partially works but only if the destinationIndexPath is less than the sourceIndexPaths of all the drag items ie in a collectionView of 5 items, flocking items at indexPaths 3 &amp; 4, and inserting them at indexPath 1 works and order is correct. But it doest work (some items get deleted, others get duplicated and order is incorrect) if I flock items at indexPath 0 &amp; 1 and try to drop them at indexPath 4. This is further complicated if some of the flocked items have sourceIndexPaths less than the destinationIndexPath and others have sourceIndexPaths greater than the destinationIndexPath.</p>
  
  <p>That author's sample project is at </p>
  
  <p><a href="https://github.com/pgpt10/DragAndDrop-CollectionView" rel="nofollow noreferrer">https://github.com/pgpt10/DragAndDrop-CollectionView</a></p>
  
  <p>Does anyone know how I can approach solving this problem.</p>