UIActivityViewController Tutorial: Sharing Data

In this UIActivityViewController tutorial, you’ll learn all about giving your users the ability to export their data and share it with others. By Owen L Brown.

Leave a rating/review
Download materials
Save for later
Share
Update note: Owen L Brown updated this tutorial for Xcode 10.1, Swift 4.2, and iOS 12. Andy Pereira wrote the original.

A lot of developers want to be able to share their app data via email, Messages or AirDrop. Sharing is a convenient way for users to send data to each other or between devices. It may even net you some new customers!

Fortunately, since iOS 6, Apple has provided the handy, but much-overlooked, UIActivityViewController class, which offers a clean interface for sharing and manipulating data inside your app.

You’ll learn everything you need to know to use this class in this UIActivityViewController tutorial!

To set up sharing inside your app, you’ll have to configure some keys inside your app’s Info.plist and handle a few system callbacks inside your app’s AppDelegate. Once set up, iOS can open your app with the URL pointing to the data to import or export.

Ready for some book sharing fun? Read on.

Getting Started

First, download the materials for this tutorial at the top or bottom of this page using the Download Materials button. Build and run the starter project in Xcode and you’ll see the following:

IActivityViewController tutorial empty books screen

Well, that’s no good; there are no books to share. Here’s how you can start sharing wonderful RW books with everyone.

UTIs and Your Plist

The first thing you need to do is set up your Info.plist to let iOS know your app can handle Book Tracker Documents.

To do this, you need to register your app as being able to handle certain Uniform Type Identifiers, or UTIs, exporting any UTIs that are not already known by the system.

In summary, UTIs are unique identifiers that represent documents. There are UTIs already built into iOS for handling common document types such as public.jpeg or public.html.

Defining Your UTIs

You’re going to register your app to handle documents with the com.raywenderlich.BookTracker.btkr UTI representing the description of a book.

You’ll give iOS information about the UTI, such as what file name extension it uses, what mime type it’s encoded as when sharing and, finally, the file’s icon.

So now it’s time to see it in action! Open Info.plist and add the following entries under the Information Property List key:

UIActivityViewController tutorial plist

You can read up on what each of these values mean in Apple’s UTI guide, but here are the important things to note:

  • The Document types entry defines what UTIs your app supports — in your case, the com.raywenderlich.BookTracker.btkr UTI, as an Owner/Editor.
  • Document types is also where you set the names of the icons that iOS should use when displaying your file type. You’ll need to make sure you have an icon for each of the sizes listed in the plist.
  • The Exported Type UTIs entry gives some information about com.raywenderlich.BookTracker.btkr, since it isn’t a public UTI. Here you define that your app can handle files ending in .btkr or files that have a mime type of application/booktracker.

Importing Your First Book

Believe it or not, by setting these keys, you have told iOS to start sending your app files that end with the .btkr extension.

You can test this out by emailing yourself a copy of the Swift Apprentice.btkr file from the Download Materials resource. Please make sure you unzip the file before emailing it to yourself. Otherwise, both the file extension UTI and mime type will be wrong.

UIActivityViewController tutorial email book attachment

You can tap on the attachment and it will prompt you to open the book in the Book Tracker app. Selecting Book Tracker will open the app. However, it won’t load the data from the sample file because you haven’t implemented the code for that yet.

Now that you’re a UTI wizard, it’s time for you to sprinkle some magic.

Note: If you don’t see “Copy to Book Tracker” displayed in UIActivityViewController after tapping the attached file in your email, you may need to edit the order of supported apps by scrolling to the end of the list, selecting More, and moving “Copy to BookTracker” to the top of the list.

Importing App Data

Before you can handle opening data from the file, you’ll need some code that can work with the file that you have passed to it.

Add that code by opening Book.swift, and replacing importData(from:) with the following:

static func importData(from url: URL) {
  // 1
  guard 
    let data = try? Data(contentsOf: url),
    let book = try? JSONDecoder().decode(Book.self, from: data) 
    else { return }
  
  // 2
  BookManager.shared.add(book: book)
  
  // 3
  try? FileManager.default.removeItem(at: url)
}

Here’s a step-by-step explanation of the code above:

  1. Verify the app can read the contents of the URL provided to it. Create a new Book object with data from the URL.
  2. Add the new book to your app’s data.
  3. Finally, delete the document that iOS saved to your app’s sandbox after opening it.
Note: If you don’t delete these files as they come in, your app will continue to grow in size with no way for the user to clear the app’s data — except… by deleting your app!

Next, when an external app wants to send your app a file, iOS will invoke application(_:open:options:) to allow your app to accept the file. Open AppDelegate.swift and add the following code:

func application(
  _ app: UIApplication,
  open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]
  ) -> Bool {
  // 1
  guard url.pathExtension == "btkr" else { return false }

  // 2
  Book.importData(from: url)

  // 3
  guard 
    let navigationController = window?.rootViewController as? UINavigationController, 
    let bookTableViewController = navigationController.viewControllers
      .first as? BooksTableViewController
    else { return true }

  // 4
  bookTableViewController.tableView.reloadData()
  return true
}

Here’s a step-by-step explanation of the code above:

  1. Verify the URL’s extension is btkr, since your app only supports files with that extension.
  2. Use the static method on Book you added above to import the data into your app.
  3. Verify the root view controller is an instance of a UINavigationController and that its first view controller is an instance of BooksTableViewController.
  4. Reload BooksTableViewController‘s table view to show the newly imported book, then return true to inform iOS that your app successfully processed the provided book information.
Note: The method still returns true even if the view controller hierarchy was not set up correctly. This works because your app has, in fact, processed the provided book information in step two above.

Build and run your app. If all works well, you should be able to open the email attachment and see the book imported into your app as shown below.

UIActivityViewController tutorial list of books imported