So what are we building?

Screenshot from Visuel App

This post is about drag & drop, so I’ll skip the creation of table view, etc. I assume you have two or more UICollectionView instances, that are probably properties of some separate objects, in my case of two different UITableViewCells.

I also assume that we want to drag & drop in every direction, from one to another and back. So the implementation is the same. Again in my case, each UITableViewCell subclass has the same implementation of UICollectionView’s drag & drop protocols.

For context, this will be our “Database”, the shared data source between collections.

In my project I’m using Firebase Realtime Database, which can’t guarantee object order like a regular array, that’s why I’m calculating the index myself.

Note that after we update model properties, the modelsSorted function will be returning different results. This function is used in func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell which means that with the next reload, it will have updated state information.

The drag delegate is pretty straightforward. We will use dragItem.localObject to pass information between collections. We also need to make sure that if we dragged an item out of the collection, we will remove it from the original one. That information we pass in session.localContext.

Drop delegate is a bit longer. Mostly because of the code which calculates the new index. Again, items are sorted from newest to oldest (Date().timeIntervalSince1970), but we change that order when we drag and drop. Please refer to the inline comments for explanations.

Also note, that when we perform collectionView.performBatchUpdates, we can delete the item only if the drag & drop was within one collection. Otherwise, we pass information through localContext to delete it from the original collection.

One extra thing that we are going to do is that we are going to highlight the area over which the user is actively dragging. We’ll do so by changing its background. This function is called continuously, so a simple timer will do the trick just fine!

If you find a mistake or have more questions, hit me up on twitter!

👋