Files and persistence
Choose the right storage location
Put application-owned data in Application Support and user-created documents where the user chooses them.
12 minute lesson
Your app has data to save. The first question is not how — it is where. macOS has conventions about where files live, and apps that ignore them lose user data at update time or fill folders that backups skip.
One place is off limits: the app bundle. The .app you ship is signed, and the signature covers every byte inside it. Writing into your own bundle breaks the signature, and the next update replaces the bundle wholesale, taking your “saved” data with it. Treat the bundle as read-only, always.
Data your app owns and manages — the notes database, in our case — belongs in Application Support. Ask FileManager for it, then add a folder named for your app:
let base = FileManager.default.urls(
for: .applicationSupportDirectory,
in: .userDomainMask
)[0]
let folder = base.appending(path: "Notes")
try FileManager.default.createDirectory(
at: folder,
withIntermediateDirectories: true
)
Always ask the API instead of hardcoding ~/Library/Application Support. In a sandboxed app — and new Xcode projects are sandboxed by default — the real location is inside your app’s container, something like ~/Library/Containers/com.flaviocopes.Notes/Data/Library/Application Support/Notes. The API resolves that for you.
createDirectory with withIntermediateDirectories: true is safe to call on every launch. It creates the folder the first time and quietly succeeds when it already exists.
Redownloadable or regenerable data goes in Caches instead:
let caches = FileManager.default.urls(
for: .cachesDirectory,
in: .userDomainMask
)[0]
The system may delete caches under disk pressure, and backups do not guarantee them. That is exactly right for thumbnails or downloaded previews, and exactly wrong for the only copy of the user’s notes.
Documents the user owns — an exported notes archive, say — are different again. Do not bury them in Application Support where nobody will find them. Let the user pick the location with a save panel, which we cover two lessons from now.
Verify your choice by running the app, saving, and finding the file in Finder. Go to Folder (⇧⌘G) with the container path gets you there. Then think through uninstall: dragging your app to the Trash leaves Application Support data behind, which is normal on macOS, but worth documenting for your users.
The mistake to recognize: building paths with string concatenation and NSHomeDirectory(). It works in development, then breaks the moment sandboxing changes the layout. FileManager.urls(for:in:) is the contract. String paths are a guess.
Lesson completed