Developer guide on the iOS file system
Learn how to work with files and directories when developing iOS applications.
10 Oct 2022 · 6 min read
Since iOS 10.3 and later, the Apple File System (APFS) is the default file system that handles persistent storage of data files.
In this developer guide, we'll look at the organisation of APFS and the rules that apply to our code when we develop iOS applications.
The sandbox directory
When in comes to reading and writing files, each iOS application has its own sandbox directory.
For security reasons, every interaction of the iOS app with the file system is limited to this sandbox directory. Exceptions are access requests to user data like photos, music, contacts etc.
The structure of the sandbox directory looks as follows:
- Bundle Container Directory
- contains the app's bundle ExampleApp.app with all of its resource files that we included within the app like images, string files, localized resources etc.
- has read-only access.
- Data Container Directory
Let's take a closer look at the listed directories.
The Documents directory
Apple recommends to use the Documents directory for user-generated content.
This includes anything a user might create, view or delete through our app, for example text files, drawings, videos, images, audio files etc. We can add subdirectories to organise this content.
The system additionally creates the Documents/Inbox directory which we can use to access files that our app was asked to open by other applications. We can read and delete files in this directory but cannot edit or create new files.
The Library directory
The Library directory contains standard subdirectories we can use to store app support files. The most used subdirectories are:
- Library/Application Support/ - to store any files the app needs that should not be exposed to the user, for example configuration files, templates etc.
- Library/Caches/ - to cache data that can be recreated and needs to persist longer than files in the tmp directory. The system may delete the directory on rare occasions to free up disk space.
When it comes to locating persisted files, a file URL is used to point to a specific location on disk, which we can then use to read or write data. In Swift, a file URL is represented by the URL type.
Accessing files within the bundle container directory
To access a resource in our app's bundle, the Foundation framework provides the Bundle type which we can use to locate a resource without knowing the structure of the bundle.
let url = Bundle.main.url(forResource: "nameOfTheResource", withExtension: "json")
In the example above, we get a file url for a specified json file which we can then use, for example to convert it to a custom Swift type.
let data = try Data(contentsOf: url)let configuration = try jsonDecoder.decode(Configuration.self, from: data)
Checkout Apple's bundle programming guide to learn more about how to access different resources from the app's bundle.
Reading and writing files within the data container directory
To manage files within the Documents or Library directories, the Foundation framework provides the FileManager type. For example, to locate the Library/Application Support directory, we can do the following:
let directoryURL = try FileManager.default.url(for: .applicationSupportDirectory,in: .userDomainMask,appropriateFor: nil,create: false)
As we can see above, we don't need to work with raw strings to access the directory. Instead, we pass in a value of FileManager's enum SearchPathDirectory. It provides values like
- .applicationSupportDirectory to access Library/Application Support
- .cachesDirectory to access Library/Caches
- .documentDirectory to access Documents
Edit: Starting with iOS 16, we can access directories even easier by using one of the URL's type properties:
To store a file in one of these directories, we could do the following:
let fileURL = directoryURL.appendingPathComponent("fileName")let data = try encoder.encode(someEncodable)try data.write(to: fileURL)
We can also use FileManager to create our own directory structure within the system directories:
let customDirectoryURL = directoryURL.appendingPathComponent("directoryName")try FileManager.default.createDirectory(at: customDirectoryURL,withIntermediateDirectories: false,attributes: nil)
Be aware, that the code above will throw an error if the directory already exists. To handle that, we could either use FileManager's fileExists(atPath:) method to check before creating or by catching and ignoring the error CocoaError.fileWriteFileExists.
Apple recommends to exclude all files from backup that we can recreate for example by downloading them from a server.
var resourceValues = URLResourceValues()resourceValues.isExcludedFromBackup = trueurl.setResourceValues(resourceValues)
Like to support my work?
Articles with related topics
How to migrate to a new schema with SwiftData in iOS
Learn how to create a migration plan in SwiftData.
20 Nov 2023 · 4 min read
How to get a SwiftData model container and context in SwiftUI
Learn how to setup a SwiftData container and context directly in SwiftUI.
30 Oct 2023 · 4 min read
Quick developer guide on SwiftData for iOS
Get an overview on Apple's SwiftData framework.
16 Oct 2023 · 4 min read
Get started with NSPredicate to filter NSFetchRequest in Core Data
Get a quick overview on how to use predicates to filter fetch request results.
20 Mar 2023 · 3 min read
How to store a Swift struct in UserDefaults
Learn about the pitfalls when using Codable types in UserDefaults.
09 Jan 2023 · 4 min read
Latest articles and tips
How to define one-to-many relationships in SwiftData
Learn to use SwiftData's @Relationship macro.
19 Feb 2024 · 4 min read
Getting started with Apollo iOS for GraphQL with Swift
Learn how to integrate GraphQL into a Swift application using Apollo iOS.
12 Feb 2024 · 8 min read
New book version release of preparing for a technical iOS job interview
Updated for iOS 17, new chapter on Machine Learning, new Q&A on Swift Data, the Observation framework and Swift's macros.
05 Feb 2024 · 2 min read
A short break for tanaschita.com
I'll be back in February 2024, with a suitcase full of fresh iOS insights and weekly articles.
18 Dec 2023 · 2 min read
Get started with auto‑renewable subscriptions for iOS
Learn how to implement in-app purchase subscriptions with StoreKit and SwiftUI.
11 Dec 2023 · 5 min read