The file system in macOS underlies every app — and the
FileManager class has a lot to do with that. Your app is stored in the Applications folder, users store documents in their Documents folder, and preferences and support files are stored in the users Library folder.
With files and data spread all over the filesystem, how can your app find out about files and folders, work with file and folder paths, and even read and write data to a file?
FileManager class — that’s how!
In this tutorial, you’ll learn how to manage directory paths, work with URLs, use common file and folder dialogs, display file and folder information, and much more!
For this tutorial, you’ll start with a playground and move on to an app later once you’ve learned the basics.
macOS uses a hierarchical file system: files & folders inside folders, inside folders. This means that finding a particular file can be complicated. Each file has its own address; the structure that defines this address is named
Open Xcode and click Get started with a playground in the Welcome to Xcode window, or choose File/New/Playground… Set the name of the playground to Files, make sure the Platform is set to macOS and click Next.
Select your Desktop and click Create to save the playground.
Once the starting playground is open, delete all the lines except for
Add the following line to your playground, but don’t worry about changing the username for now:
let completePath = "/Users/sarah/Desktop/Files.playground"
completePath now contains the address, or path, of this playground file. Since macOS is Unix-based, this is how Unix (and all its variants) describe file paths. The first slash indicates the root directory, which in this case is your startup disk. After that, every slash delimits a new folder or file. So Files.playground is in the Desktop folder in the sarah folder in the Users folder on the startup drive.
While this string describes the full path to this file, it isn’t the best way to handle addresses. Instead, you are going to convert the address into a
URL by adding:
let completeUrl = URL(fileURLWithPath: completePath)
In the results panel of the playground, you now see:
“Wait a minute!” you cry. “I thought a
URL was a web address like
https://www.raywenderlich.com, not a directory path!”
Well, yes…and yes!
URL stands for Uniform Resource Locator — which also can point to local files and folders. Instead of
https://, local file URLs start with
file://. In the results panel, it looks like there are 3 slashes, but that is because the path itself starts with a slash.
You’ve used a
String to specify a file path and converted it to a
URL. But while this is a valid
URL, it won’t work — unless your user name also happens to be sarah. Therefore, the next step is to create a
URL that works on anyone’s computer.
To do this, you’ll use the
FileManager class, which provides methods to handle most file-related actions in macOS.
The first task is to identify your Home folder and replace sarah with your own user name.
Add the following line to your playground:
let home = FileManager.default.homeDirectoryForCurrentUser
default returns the
FileManager class singleton instance, and
homeDirectoryForCurrentUser contains the
URL for the home folder of the current user.
Now that you have a
URL pointing to your home folder, you can derive the path to the playground by adding the following code:
let playgroundPath = "Desktop/Files.playground"
let playgroundUrl = home.appendingPathComponent(playgroundPath)
The results panel should show you the
URL for your own home folder.
Add these lines to the playground to query various
pathComponents property is interesting, as it separates out all folder and file names into an array. The
pathExtension properties are both quite useful in practice.
Here’s what you should have in your playground:
Note: Note that the playground file has the property
hasDirectoryPath set to
URL as representing a directory. But why is the playground file marked as a directory?
That’s because .playground files are folder bundles, just like .app files. Right-click on the playground file and select Show Package Contents to see what’s inside.
URL class makes it easy to edit
Add the following code to your playground:
var urlForEditing = home
Note how you show the
path property each time so it’s easy to see what’s changed.
While those commands edited the
URL in place, you can also create a new
URL from an existing one.
To see how to do this, insert the following commands into your playground:
let fileUrl = home
let desktopUrl = fileUrl.deletingLastPathComponent()
These methods return new
URLs, so chaining them into a sequence works well.
appending methods could have been shortened to just one, but I’ve broken them out here to make the individual steps clear to you.
Here’s what the playground should look like:
Checking for Files and Folders
NSString has a lot of file path manipulation methods, but Swift’s
String struct doesn’t. Instead, you should use
URLs when working with file paths. Working with paths in this manner will become even more important as Apple transitions to the new Apple File System (APFS).
However, there is one case where you still have to use a string representation of a file
URL: checking to see if a file or folder exists. The best way to get a string version of a
URL is through the
Add the following code to your playground:
let fileManager = FileManager.default
let missingFile = URL(fileURLWithPath: "this_file_does_not_exist.missing")
Checking whether a folder exists is slightly more obscure, as you have to check if the
URL points to a valid resource that is also a folder.
This requires what I consider a very un-Swifty mechanism of using an inout Objective-C version of a Bool. Add the following:
var isDirectory: ObjCBool = false
fileManager.fileExists(atPath: playgroundUrl.path, isDirectory: &isDirectory)
Your playground should look something like this:
A fully-annotated version of the playground can be downloaded here.
Now that you understand how to use
URL to identify files and folders, close the playground. It’s time to build an app!