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

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 = { ...

An introduction to Size Classes for Xcode 8

Introduction to Size Classes for Xcode In iOS 8, Apple introduced  size classes , a way to describe any device in any orientation. Size classes rely heavily on auto layout. Until iOS 8, you could escape auto layout. IN iOS8, Apple changed several UIKit classes to depend on size classes. Modal views, popovers, split views, and image assets directly use size classes to determine how to display an image. Identical code to present a popover on an iPad  causes a iPhone to present a modal view. Different Size Classes There are two sizes for size classes:  compact , and  regular . Sometime you’ll hear about any.  Any  is the generic size that works with anything. The default Xcode layout, is  width:any height:any . This layout is for all cases. The Horizontal and vertical dimensions are called  traits , and can be accessed in code from an instance of  UITraitCollection . The  compact  size descr...

What are the Alternatives of device UDID in iOS? - iOS7 / iOS 6 / iOS 5 – Get Device Unique Identifier UDID

Get Device Unique Identifier UDID Following code will help you to get the unique-device-identifier known as UDID. No matter what iOS user is using, you can get the UDID of the current iOS device by following code. - ( NSString *)UDID { NSString *uuidString = nil ; // get os version NSUInteger currentOSVersion = [[[[[UIDevice currentDevice ] systemVersion ] componentsSeparatedByString: @" . " ] objectAtIndex: 0 ] integerValue ]; if (currentOSVersion <= 5 ) { if ([[ NSUserDefaults standardUserDefaults ] valueForKey: @" udid " ]) { uuidString = [[ NSUserDefaults standardDefaults ] valueForKey: @" udid " ]; } else { CFUUIDRef uuidRef = CFUUIDCreate ( kCFAllocatorDefault ); uuidString = ( NSString *) CFBridgingRelease ( CFUUIDCreateString ( NULL ,uuidRef)); CFRelease (uuidRef); [[ NSUserDefaults standardUserDefaults ] setObject: uuidString ForKey: @" udid " ]; [[ NSUserDefaults standardUserDefaults ] synchro...