Document Types in SwiftUI Apps

SwiftUI supports making document-based apps that let people create and save documents. To ensure the documents have the right file extension and save and load correctly, you must configure the app’s document types. There’s not much information online about document types in SwiftUI apps so I’m sharing what I learned in this article.

Accessing the Document Type Settings

Take the following steps to access the document type settings for your SwiftUI project:

  1. Select the project file from the left side of Xcode’s project window to open the project editor.
  2. Select your app from the target list on the left side of the project editor.
  3. Click the Info button at the top of the project editor.

open with text editor panel

There are three sections of document type settings.

  • Document Types
  • Exported Type Identifiers
  • Imported Type Identifiers

A new SwiftUI document-based app project gives you a plain text editor. Unless you’re making a plain text editor, you must change the document type settings.

Document Types

Every document type in a SwiftUI app requires you to supply the following information:

  • Name
  • Identifier
  • Handler Rank

The name describes the document. Enter a descriptive name in the text field.

The identifier uniquely identifies the document type. An iOS app has a Types text field to enter the identifier. Apple has a list of system defined types for common file types. But you can also define your own type using the following convention:

com.CompanyName.DocumentName

I found in an app I’m developing that the document had the wrong file extension and type on the Mac until I made the DocumentName part of the identifier match the file extension for the document. I didn’t have this problem on iOS.

The handler rank tells Xcode whether your app owns the document type. In most cases you can choose Default.

Mac document types also require you to choose whether your app can edit documents of that type or just view them. Choose Editor to let people edit documents in your app.

Exported Type Identifiers

You need an exported type identifier for each document type your app owns. If you create a custom document type for your app, you must add an exported type identifier for the custom document type. Do not add exported type identifiers for file types your app exports.

You must supply the following information for an exported type identifier:

  • Description
  • File extension
  • Identifier
  • Conforming identifiers

If you are adding a description for a custom document type, the description usually matches the name of the document type.

Enter the file extension without the leading dot in the Extensions text field.

The identifier should match the identifier for the document type.

You may be able to avoid entering conforming identifiers, but most document types require them. The conforming identifiers are a list of identifiers the type identifier conforms to. For example if you have a custom document type that saves the document in a file package, it must conform to com.apple.package. If you look at the list of system defined types, the Apple System Base Types section has the most common conforming types.

There are also fields to enter a MIME type and a reference URL for the exported type identifier. If your document type has a MIME type or a reference URL, enter them in the appropriate fields.

Imported Type Identifiers

Imported type identifiers are for types your app uses but doesn’t own. Xcode provides an imported type identifier for your document type. If your app imports other file types, you must add imported type identifiers for the other types. If you’re making an image editor, you would add imported type identifiers for the image file formats your app supports, such as PNG and JPEG files.

You supply the same information for imported type identifiers as you do for exported type identifiers so I’m not going to repeat the information here.

SwiftUI Code for Document Types

Open the Swift file for the document struct and you should see the following code:

extension UTType {
  static var exampleText: UTType {
    UTType(importedAs: "com.example.plain-text")
  }
}
    
static var readableContentTypes: [UTType] { [.exampleText] }

If you changed the document type, you should replace the string com.example.plain-text with the identifier for your app’s document type. You should also change the variable name exampleText to something that better describes your document type.

Notice that the init for UTType has an importedAs argument. The UTType class reference in Apple’s documentation has a list of inits you can use for your document types.

The readableContentTypes property contains an array of the document types your app can read. There should be an array entry for each imported type identifier in your app. Apple has Swift enums for common document types.

SwiftUI documents also have a writableContentTypes property. This property defaults to matching the readable content types. If your app exports to a type that is not in readableContentTypes, you must add a variable for the writable content types and supply the writable types.

// Replace PDF with the file types your app
// can export and save.
static var writableContentTypes: [UTType] { [.pdf] }

Summary

The most important points about SwiftUI document types are the following:

  • Document types must have a unique identifier.
  • Add exported type identifiers for any custom document types you make.
  • Add imported type identifiers for any file types your app can import.
  • You need a UTType property in your code for the document type.
  • You need to supply a readableContentTypes array in your code with an entry for each imported type identifier.

I have a WikiDemo project on GitHub that has its own document type. Clone the project to examine the settings for the document type, exported type identifiers, and imported type identifiers.

Get the Swift Dev Journal Newsletter

Subscribe and get exclusive articles, a free guide on moving from tutorials to making your first app, notices of sales on books, and anything I decide to add in the future.

    We won't send you spam. Unsubscribe at any time.