Universal Type Identifiers Tutorial for iOS: Importing and Exporting App Data

In this tutorial, you’ll learn how to export and import app data to and from your iOS app, as well as create custom file types and extensions. By Ehab Amer.

Leave a rating/review
Download materials
Save for later
Share
Update note: Ehab Amer updated this tutorial for iOS 13, Xcode 11 and Swift 5.2. Ray Wenderlich wrote the original.

Saving your app’s data is important, but sometimes simply saving won’t cut it. You’ll find that many users also want to export their data to another app or import app data from a file.

In this tutorial, you’ll learn how to export your app’s data to an email, share it as a file and import it back into your app.

Getting Started

Download the starter project for this tutorial by using the Download Materials button at the top or bottom of this page. Open TaskList.xcodeproj inside the Starter folder.

Note: The sample project is from the Video Course Saving Data in iOS by Felipe Laso Marsetti. The app is also built using SwiftUI and Combine. If these are new topics for you, check out our SwiftUI: Getting Started and Combine: Getting Started tutorials before moving on.

The project you’ll build is an app for saving and tracking tasks you don’t want to forget. It has basic functions such as adding, editing and deleting tasks, as well as marking them complete.

TaskList App main screen

Exploring the App

Before you dive into the code, you should know a little about the project structure.

TaskList Xcode Project

The project has everything you need to do basic exporting and importing of data. You’ll enhance this project by modifying the following two files:

  • ContentView.swift is the view you see when you fist launch the app. It lists all the items in the data store with their priority.
  • TaskStore.swift is the data store of the app. Whenever you change something in the list, like add an item or mark one as completed, the store saves its current contents into a plist file in the documents directory.

Build and run your project, and you’ll see no tasks under the four priority levels.

TaskList main screen empty

So, right now you don’t have any data to export. You could add items one by one, but that would be tedious. Instead, why not import an existing list of tasks? You’ll do just that. But before you can kick off the import, you’ll create a custom file type to facilitate the process.

Creating a Custom File Type

Your app should be able to identify files it can import. At the same time, it would be convenient for your users to be able to identify file types that are compatible with your app when they see them.

To achieve this, you’re going to create a new file extension and register the new file type as something your application can import. For this tutorial, your custom file type will be .RWTL, short for Ray Wenderlich Tasks List.

Saving the New File Type

The first step in this process is to use the custom file type in the app.

The sample project already includes code to save tasks to a file. Since Task conforms to Codable, it’s easy to use Swift’s built-in PropertyListEncoder to encode a list of tasks into a property list Data blob. You can then write the data to a file on the user’s device.

To see this at work, open TaskStore.swift and look at the two lines below the shared instance declaration:

// 1
static let fileExtension = "plist"

// 2
let tasksDocURL = URL(
  fileURLWithPath: "PrioritizedTasks", 
  relativeTo: FileManager.documentsDirectoryURL)
  .appendingPathExtension(fileExtension)

In these two lines, you’re:

  1. Storing the file extension as a static variable.
  2. Constructing the URL for reading and writing the list data with the file extension and saving it to a file named PrioritizedTasks.

Now change the first line so that it uses your new file extension:

static let fileExtension = "rwtl"

Build and run, but notice that nothing changed. Well, nothing that you can see just yet. Go ahead and add an item. After this, check the app’s documents directory you’ll see that it created a new rwtl file.

TaskList app data folder

Finding the data folder can be a hassle if you navigate folder by folder. A better way is to print the value of tasksDocURL before the TaskStore loads its prioritized tasks. To do this, add the following line to the top of TaskStore‘s init:

print(tasksDocURL)

Run the app. Then open Finder, type Shift-Command-G and copy the path from the console, without the starting file:// protocol.

Path for tasksDocURL value from Xcode console

Understanding the Uniform Type Identifier

You’re using a custom extension above (“rwtl”). You could have entered anything for your extension name and it would have worked. So how does the system know the app to use for each extension?

Take JPG images as an example. Both jpeg and jpg are valid extensions. It doesn’t make sense to register the same file with the same information for each extension. But how does the system know they’re the same type?

Apple created the Uniform Type Identifier for this very purpose. It enables you to define types than can have different identifiers and representations.

Note: You can do a deep dive into Uniform Type Identifier through Apple’s documentation on UTIs.

Registering Your New UTI

To register the new file type with your app:

  1. Select the project in the Project navigator.
  2. Select the app target (not the project item) from the Targets list.
  3. Click the Info tab.

Open the target's info from Xcode

In the Document Types section, add a new entry and configure it as follows:

  • Name: TaskList Data
  • Types: com.raywenderlich.TaskList.TaskListData
  • Icon: click the + button and choose the only image available, its file name is icon-doc.png
  • Additional document type properties: Add two entries
    1. CFBundleTypeRole with type String and value Editor
    2. LSHandlerRank with type String and value Owner
  1. CFBundleTypeRole with type String and value Editor
  2. LSHandlerRank with type String and value Owner

Document Types filled values to import app data

This creates a new UTI called TaskList Data with an associated unique identifier and an icon. With the additional properties, you specify that TaskList is an editor for and owner of TaskList Data files, so that iOS knows to give it the largest level of control over these files.

Defining Import Types

So far, you defined a new UTI but didn’t enter any information about your new extension. You’ll do that next.

You’ll start with the import step before the export, though much of what you do here will also support the export process.

While still on the Info tab, look for the Imported UTIs section below Document Types. Add a new item in this section with the following information.

  • Description: TaskList Data
  • Identifier: com.raywenderlich.TaskList.TaskListData
  • Conforms To: public.data
  • Icon: click the + button and choose the only image available, its file name is icon-doc.png
  • Additional imported UTI properties: Add one entry UTTypeTagSpecification of type Dictionary. Inside it, add one item with the key public.filename-extension of type Array and inside it add two values rwtl and RWTL.
Note: To add entries inside a dictionary or array in the properly list editor, you must click the disclosure triangle next to the key name. If the triangle is pointing down, you’ll be able to add entries.

Imported UTIs fields to import app data

With this, you connect the document type you created earlier with two file extensions: .rwtl and .RWTL. iOS will now launch your app when a user tries to use a file with one of these extensions. When defining imported UTIs, make sure the that identifier matches the types you defined in the Document Types section.

You also need to let iOS know about how you plan to import app data. Open Info.plist and add the following two keys:

  • LSSupportsOpeningDocumentsInPlace with a value of NO, indicating that documents should be copied before they are imported into your app.
  • UISupportsDocumentBrowser with a value of NO, indicating that your app is not a document-based app.

Build and run, then close the app in the simulator to show the home screen. Remember the PrioritizedTasks.rwtl file that you downloaded with the starter project? Try dropping that file onto the simulator.

TaskList main screen empty

Notice that this action launches the app. Awesome way to open files, huh? :]