FileManager is a class from the Foundation framework that provides an interface for working with the file system on iOS, macOS and other Apple platforms. It allows you to create, read, move and delete files and directories, as well as manage metadata and access permissions. In iOS, all FileManager operations are limited by the application Sandbox. According to Apple Developer Documentation (2026), FileManager is thread-safe and can be used from background threads, but all file system operations must be performed considering the sandbox and Security-Scoped Bookmarks access permissions.
Key Takeaways
FileManager is a singleton class from the Foundation framework that provides a unified API for interacting with the file system on all Apple platforms. It is available through FileManager.default or by creating an instance with a custom delegate.
The main capabilities of the class include: checking file existence (fileExists), creating directories (createDirectory), copying and moving (copyItem, moveItem), deleting (removeItem), getting attributes (attributesOfItem) and directory contents (contentsOfDirectory). FileManager is closely related to NSData, String and JSONEncoder/Decoder for data serialization.
FileManager is thread-safe: Apple guarantees safe method calls from different threads. However, file system operations can be slow on large files, so Apple recommends performing them on a background queue (DispatchQueue.global) and calling FileManagerDelegate methods to report progress.
let fileManager = FileManager.default
let documentsURL = fileManager.urls(
for: .documentDirectory,
in: .userDomainMask
).first!
let fileURL = documentsURL.appendingPathComponent("data.plist")
if fileManager.fileExists(atPath: fileURL.path) {
print("File exists at \(fileURL.path)")
}
Each iOS app has three main directories accessible through FileManager within the Sandbox: Documents, Library and tmp. Each has its own purpose and backup rules that are critical to follow for passing App Store review.
Documents — for user data that should persist between launches and be backed up to iCloud. Library — for app files: caches (Caches), settings (Preferences), databases (Application Support). tmp — for temporary files that can be deleted by the system at any time between app launches.
| Directory | FileManager URL | Backup | Usage |
|---|---|---|---|
| Documents | .documentDirectory | Yes | User data, files, export |
| Library/Caches | .cachesDirectory | No | Image caches, temporary data |
| Library/Preferences | .libraryDirectory + "Preferences" | Yes | UserDefaults, app settings |
| Library/Application Support | .applicationSupportDirectory | Yes | Databases, CoreData, Realm |
| tmp | .tmpDirectory (NSTemporaryDirectory) | No | Temporary session files |
Apple's rule: if a file can be recovered from the internet or recreated — it should be stored in Caches (no backup). If a file contains user data — Documents (with backup). Incorrect file placement is one of the common reasons for app rejection, as Apple checks compliance with Storage & iCloud Backup Guidelines.
FileManager itself does not provide methods for reading file contents — for that use NSData(contentsOf), String(contentsOf) or FileHandle methods. FileManager is responsible for managing files: checking existence, moving, copying, deleting.
To write data use the createFile(atPath:contents:attributes:) method or high-level APIs — data.write(to:), JSONEncoder.encode and PropertyListEncoder. FileManager also provides FileHandle for streaming read and write of large files, which does not load the entire file into memory.
struct UserSettings: Codable {
let username: String
let isDarkMode: Bool
let fontSize: Int
}
let settings = UserSettings(
username: "developer",
isDarkMode: true,
fontSize: 16
)
// Write JSON to Documents
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let data = try encoder.encode(settings)
let url = documentsURL.appendingPathComponent("settings.json")
try data.write(to: url, options: .atomic)
// Read JSON
let loadedData = try Data(contentsOf: url)
let loadedSettings = try JSONDecoder()
.decode(UserSettings.self, from: loadedData)
When writing, use options: .atomic — this ensures the file will not be corrupted if the write fails: data is first saved to a temporary file, then atomically moved to the target path. For reading large files, use FileHandle with .readingMode and read data in chunks, controlling memory consumption.
FileManager provides methods for full directory management: createDirectory (creating all intermediate folders via withIntermediateDirectories), contentsOfDirectory (getting a file list), enumeratorAt (recursive traversal) and subpathsOfDirectory (all paths within a directory).
The enumeratorAt method returns a DirectoryEnumerator, which allows efficiently traversing large directories without loading all contents into memory. It supports filtering via skipDescendants and provides attributes of each item without an additional file system query.
// Recursive directory traversal
if let enumerator = fileManager.enumerator(
at: documentsURL,
includingPropertiesForKeys: [.fileSizeKey, .isDirectoryKey]
) {
for case let fileURL as URL in enumerator {
let attrs = try fileURL.resourceValues(
for: [.fileSizeKey, .isDirectoryKey]
)
if attrs.isDirectory == false {
let size = attrs.fileSize ?? 0
print("File: \(fileURL.lastPathComponent), Size: \(size) bytes")
}
}
}
To delete a directory use removeItem(at:). Warning: deleting a directory in iOS is irreversible — files do not go to the trash as on macOS. Before deleting, make sure you no longer need the files from that directory, and perform the operation on a background thread, as deleting many files can block the UI.
FileManager integrates with iCloud Drive through the URLForUbiquityContainerIdentifier method, which returns the URL of the iCloud directory for the app. This requires enabling the iCloud capability in the project and adding the appropriate entitlement.
iCloud files sync automatically, but FileManager provides methods for manual control: startDownloadingUbiquitousItem forces download, evictUbiquitousItem removes the local copy, and urlOfItem(at:) returns the local URL for an iCloud file. NSMetadataQuery is used for searching files in iCloud.
Critical limitation: iCloud Drive is not supported for files in the Documents directory — only for files in ubiquityContainer. Do not try to sync Documents via iCloud; for that use NSUbiquitousKeyValueStore for small amounts of data or Core Data with CloudKit for complex structures.
FileManager operations can be expensive, especially on devices with slow flash memory. Apple's main recommendations include performing all file operations on background queues, minimizing the number of fileExistsAtPath calls, and caching results.
The fileExists method performs a stat() system call, which is relatively slow. If you check for file existence before reading, it is better to just attempt to read it and handle the error — this performs the same stat but avoids a double system call. For bulk checks, use enumeratorAt with resourceValues.
For optimizing work with large data volumes:
Apple Instruments provides the File Activity template for profiling file operations. Use it to identify bottlenecks — for example, frequent fileExists calls in a loop or write operations on the main thread. The most common performance issues are related to synchronous writing of large files when the app is being suspended.
Frequently Asked Questions
FileManager is a Foundation framework class for working with the Apple file system. It provides an API for creating, reading, moving, deleting files and directories. In iOS, its operation is limited to the application Sandbox, except for Security-Scoped Bookmarks.
Documents — user data with iCloud backup. Library/Caches — caches without backup. Library/Application Support — databases. tmp — temporary files. App Group Container — for shared data between apps in the same group.
Call FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first. The method returns a URL with the absolute path to the Documents directory inside the current app's Sandbox. Use fileExists(atPath:) to check existence.
No, iOS Sandbox prevents access to other apps' file systems. Exceptions: App Groups (shared directory for apps from the same developer) and Security-Scoped Bookmarks (file access through UIDocumentPicker and iCloud Drive).
Use the .atomic option when writing — data is first saved to a temporary file, then atomically moved to the target path. This prevents file corruption on write failure. For large data, use FileHandle with chunked writes of 1-2 MB.
Summary
We will develop a mobile application turnkey
IT Sectr creates iOS and Android applications for startups and businesses since 2017. We will advise you and propose the best solution.
Read also