Skip to main content

Working with Drag and Drop APIs in iOS 11

Drag and Drop APIs in iOS 11

Welcome to the first part of the Drag and Drop series! In this tutorial, you will learn how to implement the drag and drop functionality onto a UIViewController. In the next part of the series, you will learn how to use the Drag and Drop APIs with UITableViewControllers and UICollectionViewControllers .
One of the most anticipated releases of iOS 11 was the announcement of several new Drag and Drop APIs. So for those of you who aren’t familiar with Drag and Drop, it is a way to graphically move or copy data from one application to another or sometimes within the same application.
There are a lot of examples where you can implement Drag and Drop into your apps and while there are a numerous number of APIs for you to implement for different scenarios, it is really easy to implement. I’ll be teaching you how you can implement Drag and Drop within your apps specifically regarding to the UIViewController. Let’s get started!
Note: These Drag and Drop APIs work only on Swift 4 and iOS 11 so make sure you are running this on Xcode 9 or above.

Introduction to Drag and Drop

As mentioned earlier, Drag and Drop is a graphical way to move or copy data between two applications. Here’s some quick terminology:
  1. Source App: The app from which the item or information is dragged (copied)
  2. Destination App: The app from which the item or information is dropped (pasted)
  3. Drag Activity: The dragging action, from start to finish.
  4. Drag Session: The items which are dragged, managed by the system, throughout teh drag activity
Note: Dragging and Dropping between apps is supported only on iPads. For iPhone, the source app is the same as the destination app.
A really neat fact about Drag and Drop is that while you are dragging items from one app to another, the source and destination apps continue processing as usual. Therefore, these two actions are synchronous. You can continue operating an app with another finger or start a new drag activity.
Also, there is no need to incorporate these APIs into UITextViews and UITextField as they automatically support drag and drop. You can configure UICollectionViewsUITableViews, and almost any view to support Drag and Drop.
For this tutorial, we’ll focus on adding Drag and Drop into UIViewControllers. Let’s dive into the implementation.

How to Implement Dropping

First, download the starter project over here. As you can see, we have a simple ViewController with two UIImageViews that are already linked to the code. These two image views are designed for you to drop an image. Now all we have to do is start coding!
Let’s start with integrating the Dropping APIs. We can now implement the API in several short steps. Our first step is to add the UIDropInteractionDelegate to the ViewController. So adjust the class to look like this:
Next, we have to add an interaction recogniser to our view. This can be implemented in our viewDidLoad method. After super.viewDidLoad(), type the following line:
Now, to make our class conform to the UIDropInteractionDelegate, we have to implement 3 methods. I will explain each one to you.
  1. func dropInteraction(_ interaction: UIDropInteraction, performDrop session: UIDropSession)
    This method tells the delegate it can request the item provider data from the session’s drag items.
  2. func dropInteraction(_ interaction: UIDropInteraction, sessionDidUpdate session: UIDropSession) -> UIDropProposal
    This method tells the delegate that the drop session has changed. In our case, we want to copy the items if the session has updated.
  3. func dropInteraction(_ interaction: UIDropInteraction, canHandle session: UIDropSession) -> Bool
    This method check to see if the view can handle the session’s drag items. In our scenario, we want the view to accept images as the drag item.
Let’s first implement the second and third methods like this:
In the dropInteraction(_:sessionDidUpdate:) method, we return a UIDropProposal object and specify it’s a copy operation. You must return a UIDropProposal object if a view’s drop interaction delegate accepts dropped items. For the dropInteraction(_:canHandle:) method, the return value of the implementation indicates whether the drop is accepted. In the code above, we only accept drop activities that contain images.
We are almost done. We now have to add the code that will allow the app to perform the drop onto the view. Copy and paste the code below:
  1. Sometimes, when we drag an image onto our board, we may end up dragging more than one image. This returns an array session.items, so we run the following code for each dragItem.
  2. We load the object which are UIImage in the dragItems.
  3. In case of an error, we use a guard statement to handle the error. If an error exists (say, the item doesn’t conform to the UIImage class), then we print an error message.
  4. If there is no error, we set the image of imageView to draggedImage.
  5. We determine where the finger is placed in order to see if we set the image to the first imageView or the second imageView. Notice that the center of the image is exactly where our finger is.
Now, we are done! Let’s run the app and check to see how well it works! But, first make sure your code looks something like this:
Dragging and Dropping between apps is supported only on iPads. So if you want to drag and image from Safari or Photos and drop it onto the view, you will need to run the sample app on an iPad. iPhone only supports dragging and dropping within the app. On a simulator, it may take sometime for the image to copy itself onto the board.
If you follow me correctly, your app should run as expected! But what if you made a mistake and want to drag the image in the first image view into the second? Well it’s quite simple! Now, we have to implement the dragging API.

Dragging an item

Now, say that the image we had in our board was a mistake and we wanted it to be removed. Well, this would require us to drag the image to another location. To achieve this, we would need to implement the dragging APIs. Let’s see how it’s done!
First, let’s add the UIDragInteractionDelegate. To do this, we simply have to add UIDragInteractionDelegate to the list of protocols in our class:
Now you might get an error and that’s because we have not implemented the required protocol stubs in our code. Unlike the UIDropInteractionDelegate where we needed 3 methods to adhere to the protocol, we need only one in this case. Add this function at the end of the code:
This method is basically used for detecting the type of object being dragged and how to handle it.
Before we implement this method, we need to modify our viewDidLoad code slightly. Since we’ll be touching the image view, we need to enable the userInteraction property for both image views. Modify the viewDidLoad method to look like this:
Now, we’re almost done. Modify your dragInteraction(:_) function to this.
And that’s all! Run your code and see if you can drag and drop between images from your Photos albums or the web. Copy them from the first image view to the second image view! It’s a drag fest! Check out the result below!

What’s Next

As you can see, it’s quite simple to add Drag and Drop to your apps enabling your app to activate a whole new set of powerful APIs. In this tutorial, you learned how to drag and drop images, but this can be applied to text as well! What’s more is that drag and drop in different view controllers such as UITableViews and UICollectionViews can really provide a seamless experience for your users.
To download the complete project, you can do so from the Github repository here.
To learn more about Drag and Drop, I recommend checking out some of these video from WWDC 2017!
  1. Introducing Drag and Drop
  2. Mastering Drag and Drop
  3. Drag and Drop with Collection and Table View
  4. Data Delivery with Drag and Drop
Finally, here is Apple’s Official Documentation on Drag and Drop.
Let me know what you think of the tutorial and whether or not you would like to see a series on Drag and Drop!

Comments

Popular Posts

How I Reduced the Size of My React Native App by 85%

How and Why You Should Do It I borrowed 25$ from my friend to start a Play Store Developer account to put up my first app. I had already created the app, created the assets and published it in the store. Nobody wants to download a todo list app that costs 25mb of bandwidth and another 25 MB of storage space. So today I am going to share with you how I reduced the size of Tet from 25 MB to around 3.5 MB. Size Matters Like any beginner, I wrote my app using Expo, the awesome React Native platform that makes creating native apps a breeze. There is no native setup, you write javascript and Expo builds the binaries for you. I love everything about Expo except the size of the binaries. Each binary weighs around 25 MB regardless of your app. So the first thing I did was to migrate my existing Expo app to React Native. Migrating to React Native react-native init  a new project with the same name Copy the  source  files over from Expo project Install all de...

How to recover data of your Android KeyStore?

These methods can save you by recovering Key Alias and Key Password and KeyStore Password. This dialog becomes trouble to you? You should always keep the keystore file safe as you will not be able to update your previously uploaded APKs on PlayStore. It always need same keystore file for every version releases. But it’s even worse when you have KeyStore file and you forget any credentials shown in above box. But Good thing is you can recover them with certain tricks [Yes, there are always ways]. So let’s get straight to those ways. 1. Check your log files → For  windows  users, Go to windows file explorer C://Users/your PC name/.AndroidStudio1.4 ( your android studio version )\system\log\idea.log.1 ( or any old log number ) Open your log file in Notepad++ or Any text editor, and search for: android.injected.signing and if you are lucky enough then you will start seeing these. Pandroid.injected.signing.store.file = This is  file path where t...

React Native - Text Input

In this chapter, we will show you how to work with  TextInput  elements in React Native. The Home component will import and render inputs. App.js import React from 'react' ; import Inputs from './inputs.js' const App = () => { return ( < Inputs /> ) } export default App Inputs We will define the initial state. After defining the initial state, we will create the  handleEmail  and the  handlePassword  functions. These functions are used for updating state. The  login()  function will just alert the current value of the state. We will also add some other properties to text inputs to disable auto capitalisation, remove the bottom border on Android devices and set a placeholder. inputs.js import React , { Component } from 'react' import { View , Text , TouchableOpacity , TextInput , StyleSheet } from 'react-native' class Inputs extends Component { state = { ...