FileManager Class Tutorial for macOS: Getting Started with the File System

In this tutorial, learn to use the FileManager class in a macOS app. Work with files, folders and navigate the file system while creating a working app. By Sarah Reichelt.

3.5 (11) · 2 Reviews

Save for later
Share

Contents

Hide contents

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?

The 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!

Getting Started

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 URL.

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.

New Playground

Note: For this tutorial, the name of the playground must be Files and it must be located on your Desktop. If you gave it a different name or saved it somewhere else, please rename it and move it before proceeding, or else the code below just won’t work!

Once the starting playground is open, delete all the lines except for import Cocoa.

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: file:///Users/sarah/Desktop/Files.playground

Create a URL

“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.

FileManager Class

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 URL properties:

playgroundUrl.path
playgroundUrl.absoluteString
playgroundUrl.absoluteURL
playgroundUrl.baseURL
playgroundUrl.pathComponents
playgroundUrl.lastPathComponent
playgroundUrl.pathExtension
playgroundUrl.isFileURL
playgroundUrl.hasDirectoryPath

The pathComponents property is interesting, as it separates out all folder and file names into an array. The lastPathComponent and pathExtension properties are both quite useful in practice.

Here’s what you should have in your playground:

URL Components

Note: Note that the playground file has the property hasDirectoryPath set to true. This marks the 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.

Note: Note that the playground file has the property hasDirectoryPath set to true. This marks the 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.

The URL class makes it easy to edit URLs.

Add the following code to your playground:

var urlForEditing = home
urlForEditing.path

urlForEditing.appendPathComponent("Desktop")
urlForEditing.path

urlForEditing.appendPathComponent("Test file")
urlForEditing.path

urlForEditing.appendPathExtension("txt")
urlForEditing.path

urlForEditing.deletePathExtension()
urlForEditing.path

urlForEditing.deleteLastPathComponent()
urlForEditing.path

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
    .appendingPathComponent("Desktop")
    .appendingPathComponent("Test file")
    .appendingPathExtension("txt")
fileUrl.path

let desktopUrl = fileUrl.deletingLastPathComponent()
desktopUrl.path

These methods return new URLs, so chaining them into a sequence works well.

The three 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:

Append Path to a URL

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 path property.

Add the following code to your playground:

let fileManager = FileManager.default
fileManager.fileExists(atPath: playgroundUrl.path)

let missingFile = URL(fileURLWithPath: "this_file_does_not_exist.missing")
fileManager.fileExists(atPath: missingFile.path)

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)
isDirectory.boolValue

Your playground should look something like this:

FileManager Class Check For File Exists

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!