In this tutorial, I’ll show you how to embrace iOS 11’s Files app. First, I’ll walk you through configuration of an app so that any files stored in its iOS file system-based “Documents” folder are made visible in the Files app and exposed to other apps installed on your device. Second, I’ll demonstrate how you can incorporate Files app-like interface and functionality into your own apps. All of the Swift code I wrote to accomplish these two tasks is included below — and I’ve taken lots of screenshots regarding Files app integration. Sit back, enjoy, and learn about a fundamental paradigm shift in the iOS zeitgeist, moving from a “hide-the-details” (like hiding individual files) mindset to providing users with the ability to look at and manipulate files related to their apps using a macOS Finder-like interface, except on iOS.
To pique your interest, let’s look at a feature I encoded in the final app for this tutorial. We’ll use my app, named “Document-Based App,” to view an image file in the app’s main folder:
Introduction
Most iOS app developers — and users — are not accustomed to seeing the files associated with their apps, at least not in a Finder-like or Explorer-like or even command line-like listing format. In other words, they’re not used to seeing files organized as just files and directories and being able to navigate around in a file system. For years, the closest thing to an iOS file browser has been through apps like Photos, where you can see individual thumbnail images of photos hinting at the fact that their content is stored in individual files. But Photos gives you no sense of how the image files are organized… In folders or subfolders? Which folders and where in your device’s file system?
iOS 11 changed all that with the introduction of the Files app.
Note that before the Files app, developers like myself had to build custom Finder-like hierarchical file/directory user interface (UI) representations of the iOS file system, and provide corresponding functionality for navigation and manipulation of files and folders. Download one of my iPad-based apps to see an example of my custom file “explorer” or “finder” here — it’s a free app.
Exposing Your App’s File to the Files App
Let’s first walk through the basic use of the Files app. Remember that you must be running iOS 11 to follow along with this tutorial. I’ve found that many people out there, even amongst developers, haven’t even used the Files app yet. Let’s look at how the app works, and remember that today I’m limiting my discussion only to files stored locally on a device — an iPhone in this case. Getting into iCloud or Dropbox support is too much for one tutorial. I’ll start up the Files app and show you how to view files stored locally on your device:
For the purposes of this tutorial, we’ll always want to “Browse” to the “location” called “On My iPhone,” as you just saw in the previous graphic.
Whether you actively use it or not, every iOS app you develop has its own unique sandboxed file system comprised of a set of directories, most notably the “Documents” directory. Detailed discussion of the iOS file system’s structure and how you perform tasks like reading, writing, deleting, renaming, moving, and listing files is beyond the scope of this tutorial, but don’t worry if this is all new to you. I’ve wrote several detailed tutorials covering most salient iOS file management topics, for example, here and here.
Developers who want to expose certain app files to users should always use the “Documents” directory. Files meant for internal use, like templates or configuration files, or temporary files say, used for converting files between different formats, should be stored in other predefined sandboxed folders like “Library/” or “tmp/”.
Opting your app into showing its files in the Files app
Caution: By exposing your app’s files to the Files app, you’re also making those same files available to other developers’ apps. Think about it carefully before you write things like a user’s personal information or details about your own proprietary trade secrets into files that will be made possibly public.
Configuring your app so that its files appear in the Files app is pretty simple. I’ll show you how by setting up the app I used in a tutorial for explaining the iOS file system, named “iOS File Management.” It’s a great candidate for opting into the Files app because it contains Swift code for reading, writing, deleting, renaming, moving, and listing iOS files.
The easiest way to configure the app is to add the following two keys inside the main
<dict>
in the Xcode project’s Info.plist
file:
Remember that you can view and edit an Xcode project’s
Info.plist
file as XML by:- going to the Project Navigator;
- right-clicking or control-clicking on the
Info.plist
file; and, - selecting Open As -> Source Code from the context menu.
If you prefer to edit the
Info.plist
file through Xcode’s default property list interface, hover your mouse over an existing entry and press the plus sign (+) that appears. Add the two keys I showed above and set each of their Value toggles to “YES,” like so:
There are good definitions of both of these keys at this link. You can see my project’s
Info.plist
file with these two keys added here and the whole project here in my GitHub repo.
I’ll now install the newly-configured “iOS File Management” app on my iPhone. I added some code in the
viewDidLoad
method of my only UIViewController
subclass. That code runs on app startup and writes a text file named “textFile1.txt” into the app’s “Documents” folder.
Let’s look for that file in the Files app:
See the folder representing my “iOS File Management” app’s files? It contains the file, “textFile1.txt,” that I encoded to be written on startup of the app. You can even see a thumbnail via (Quick Look) previewing the contents of my text file. Here’s some iOS documentation from Apple that describes the keys I added to my “iOS File Management” app’s
Info.plist
file, providing the perfect segue
(segue?) — into the rest of this tutorial:To give other apps access to the files in your Documents directory, just set the proper keys in your app’s Info.plist file. You can either set the UISupportsDocumentBrowser key (for document browser-based apps), or set both the UIFileSharingEnabled and LSSupportsOpeningDocumentsInPlace keys.These keys enable other apps to open and edit the contents of your Documents directory in place. Your files also appear in both the Files app and the document browser. For more information, see the UIDocumentBrowserViewController class.
Providing a File App-like Experience
Let’s pick up right where we left off in the last section of this tutorial where I mentioned building “document browser-based apps” using a
UIDocumentBrowserViewController
. In other words, you can provide an iOS 11 Filesapp-like experience in your own apps. This is especially useful if your business model relies heavily on storing and manipulating information in flat files, like image files, audio files, video files, etc., or files that encode some kind of design representations, like CAD or vector graphics files.
I strongly encourage you to use Xcode to create a new project based on the iOS Document Based App template (see next section), review it thoroughly, and follow along with my steps in this tutorial. I’ll tell you when I customize the template code, show you what code I’ve edited or added, and explain my changes to the template code. Please follow along.
Starting with a Document Based App template
To get started, open Xcode and go to File, New ->, Project…, select iOS, and select the Document Based App template:
Click the Next button, fill out the usual new project details, and choose a location for your new project. You’ll notice later that I named my Document Based App template project “Document-Based App.” You’ll need to turn on Signing under your app target’s General settings tab.
Here’s the project file/bundle structure for the Document Based App template:
Here’s the storyboard that comes preconfigured with that same project template:
Configuring the document types your app will support
When you create Xcode projects that can manipulate files, there’s a bit of configuration you must do to tell the app what kind of files it can manipulate. For example, the Document Based App template app is minimally usable in terms of providing you with the Files app interface and allowing you to tap on and see a little meta data about image files (recognized by the “public.image” uniform type identifier or “UTI”). Apple decided that the template would support images, but I want to support text files, too.
Make sure the Document Based App template project you created is open in Xcode and:
- go to the Project Navigator;
- find and click on the project’s target;
- select the Info tab;
- scroll down to and find the Document Types section; and,
- expand the Document Types disclosure triangle.
Here’s what you’ll see:
As I’d mentioned and as you can see in the previous image, your app is already configured to notice and open image type files. To add support for text files, click the plus (+) sign that I highlighted in blue in the previous image and fill in the various fields so that you have a second document type. The Document Types section will now have a new entry that looks like this:
If you prefer manipulating XML in your
Info.plist
file, you can add document type support for image and text files inside the main <dict>
section:Other preconfigured app options
The Document Based App template app comes preconfigured with its
Info.plist
containing the UISupportsDocumentBrowser
key set to YES (or <true/>
in XML). This is absolutely essential for your app to provide Files app-like behavior. You can read about this key here.
Since your app now declares the
UISupportsDocumentBrowser
key, that has the same effect as declaring the UIFileSharingEnabled
and LSSupportsOpeningDocumentsInPlace
key combination as discussed above in the section entitled “Opting your app into showing its files in the Files app.” You’ll be exposing your app’s files to the Files app and you’ll also be making those same files available to other developers’ apps. Think about it carefully before you write things like a user’s personal information or details about your own proprietary trade secrets into files that will be made possibly public.The Implementation for a Files App-like Experience
I started with an Xcode iOS Document Based App template and customized it so that I could: 1) browse for, open, display, edit, and save UTF-8 encoded text files and 2)browse for, open, and display .PNG and .JPG image files. Let’s walk through my project code.
Browsing for and selecting documents with UIDocumentBrowserViewController
The preliminaries for browsing documents and opening documents are already configured for you in Xcode’s iOS Document Based App template. A user interface for navigating and selecting documents, identical to what the Files app provides, is furnished for you. You start coding when you want to add functionality for reading the contents of user-selected documents into a document model, editing contents, writing the edited contents back to the original file, writing contents to a new file name/path, creating new files, closing the original file, and a number of other operations.
I modified the
Main.storyboard
a bit later in the process of customizing the project template, especially the “Document View Controller” scene on the right. But we need to look at the scene on the left to get started, the “Document Browser View Controller” scene, whose backing class is DocumentBrowserViewController
in file DocumentBrowserViewController.swift
. Notice it has the Storyboard Entry Point
:
App template file:
I’m going to describe my code in a series of steps — steps that are also comments in my code shown below. I’ll show you my code first, then describe the steps/comments.
DocumentBrowserViewController.swift
I’m going to describe my code in a series of steps — steps that are also comments in my code shown below. I’ll show you my code first, then describe the steps/comments.
I’ve only made minimal changes to the template code in
DocumentBrowserViewController.swift
, so I won’t show the original template, I’ll just show you my code and explain the comments I added:
#1.0 – When my app starts up, an instance
DocumentBrowserViewController
is created. That object, an instance of a subclass of UIDocumentBrowserViewController
, is initialized via a callback to its viewDidLoad
method. Notice it adopts the UIDocumentBrowserViewControllerDelegate
protocol, whose main job is to notify the developer about user interactions with the document browser.
#1.1 – Set the
delegate
property of the UIDocumentBrowserViewControllerDelegate
protocol to the DocumentBrowserViewController
class. By doing so, the DocumentBrowserViewController
class gets notified of user interactions with the document browser and UIDocumentBrowserViewControllerDelegate
callbacks get invoked.
#1.2 – I commented out code to allow document creation, I left multiple document selection disabled, and left code for changing the appearance of the document browser commented out as it originally was as-is in the template. I didn’t want to get too fancy in this introductory tutorial.
#2.0 – When a user taps on a document icon in the browser interface,
documentBrowser(_:didPickDocumentURLs:)
is called. As Apple describes the process, “When the user selects one or more documents in the browser view controller, the system calls your delegate’s documentBrowser(_:didPickDocumentURLs:) method” with the URL
corresponding to the document icon that the user tapped/selected.
#2.1 – Then
documentBrowser(_:didPickDocumentURLs:)
calls the template project’s presentDocument(at documentURL: URL)
method to give the developer a chance to prepare for and display the document’s contents, and/or display meta data about the document, and/or do something else with the selected document.
#3.0 – Prepare for and present my custom user interface which uses a
UIDocument
subclass to manipulate and/or display the user-select document.
#3.1 – Get the “Document View Controller” scene on the right side of
Main.storyboard
, which is backed by the DocumentViewController
class, a subclass of UIViewController
, in the DocumentViewController.swift
file, and instantiate it. That’s my custom UI which we’ll discuss in detail later.
#3.2 – In the template project, the
DocumentViewController
class has a member document
of type UIDocument
, which is an “abstract base class.” According to Apple, “A document-based application must create a subclass of UIDocument
for its documents.” An instance of my UIDocument
subclass is initialized with the URL
of the document that was selected by the user in my UI. My UIDocument
subclass is initialized using init(fileURL: URL)
.
#3.3 – Finally,
present(_:animated:completion:)
is called and my customized UI, based on the work I did in Main.storyboard
to add features to the DocumentViewController
, and the work I did in DocumentViewController.swift
, is displayed.Opening, displaying, editing, closing the selected UIDocument
App template file
DocumentViewController.swift
contains a subclass of UIViewController
which, in concert with its counterpart, the “Document View Controller” scene in Main.storyboard
, provides a simple user interface for displaying the name of the document the user selected as described in the previous section. Notice that it declares a property document
of type UIDocument
while Apple admonishes us that “A document-based application must create a subclass of UIDocument for its documents.”
App template file:
Here’s the skeletal app template file as generated by Xcode:
DocumentViewController.swift
Here’s the skeletal app template file as generated by Xcode:
I’ve extended and enhanced this file and its corresponding “Document View Controller” scene quite a bit. First, let me show you the user interface I built in the “Document View Controller” scene in
Main.storyboard
for viewing and editing documents:
Comments
Post a Comment
Thank You.